Exemplo n.º 1
0
    def measure_aodm(self, nsig=3., normalize=True):
        """ AODM calculation

        It sets these attributes:
          * self.attrib[ 'N', 'sig_N', 'logN', 'sig_logN' ]:
            Column densities and errors, linear and log

        Parameters
        ----------
        nsig : float, optional
          Number of sigma significance required for a "detection"
        normalize : bool, optional
          Normalize first?
        """
        # Cut spectrum
        fx, sig, xdict = self.cut_spec(normalize=normalize)
        velo = xdict['velo']
        # Check that there is sufficient data
        if len(fx) <= 1:
            warnings.warn("Spectrum does not cover {:g}".format(self.wrest))
            self.attrib['flag_N'] = 0
            return

        # Calculate
        N, sig_N, flg_sat = laa.aodm((velo, fx, sig),
                                     (self.wrest, self.data['f']))

        # Flag
        if flg_sat:
            self.attrib['flag_N'] = 2
        else:
            if N > nsig * sig_N:
                self.attrib['flag_N'] = 1
            else:
                self.attrib['flag_N'] = 3

        # Values
        self.attrib['N'] = N
        self.attrib['sig_N'] = sig_N

        # Log
        laa.log_clm(self.attrib)
Exemplo n.º 2
0
    def measure_aodm(self, nsig=3., normalize=True):
        """ AODM calculation

        It sets these attributes:
          * self.attrib[ 'N', 'sig_N', 'logN', 'sig_logN' ]:
            Column densities and errors, linear and log

        Parameters
        ----------
        nsig : float, optional
          Number of sigma significance required for a "detection"
        normalize : bool, optional
          Normalize first?
        """
        # Cut spectrum
        fx, sig, xdict = self.cut_spec(normalize=normalize)
        velo = xdict['velo']
        # Check that there is sufficient data
        if len(fx) <= 1:
            warnings.warn("Spectrum does not cover {:g}".format(self.wrest))
            self.attrib['flag_N'] = 0
            return

        # Calculate
        N, sig_N, flg_sat = laa.aodm((velo, fx, sig), (self.wrest,self.data['f']))

        # Flag
        if flg_sat:
            self.attrib['flag_N'] = 2
        else:
            if N > nsig*sig_N:
                self.attrib['flag_N'] = 1
            else:
                self.attrib['flag_N'] = 3

        # Values
        self.attrib['N'] = N
        self.attrib['sig_N'] = sig_N

        # Log
        laa.log_clm(self.attrib)
Exemplo n.º 3
0
    def measure_aodm(self, nsig=3.):
        """ AODM calculation

        It sets these attributes:
          * self.attrib[ 'N', 'sigN', 'logN', 'sig_logN' ]:
            Column densities and errors, linear and log

        Parameters
        ----------
        nsig : float, optional
          Number of sigma significance required for a "detection"
        """
        # Cut spectrum
        fx, sig, xdict = self.cut_spec(normalize=True)
        velo = xdict['velo']

        # Calculate
        N,sigN,flg_sat = laa.aodm( (velo, fx, sig), (self.wrest,self.data['f']) )

        # Flag
        if flg_sat:
            self.attrib['flagN'] = 2
        else:
            if N > nsig*sigN:
                self.attrib['flagN'] = 1
            else:
                self.attrib['flagN'] = 3

        # Values
        self.attrib['N'] = N
        self.attrib['sigN'] = sigN

        # Log
        logN, sig_logN = laa.log_clm(self.attrib)
        self.attrib['logN'] = logN # Dimensionless
        self.attrib['sig_logN'] = sig_logN # Dimensionless
Exemplo n.º 4
0
    def synthesize_colm(self, overwrite=False, redo_aodm=False, **kwargs):
        """Synthesize column density measurements of the component.
        Default is to use the current AbsLine values, but the user can
        request that those be re-calculated with AODM.

        Parameters
        ----------
        overwrite : bool, optional
          Clobber any previous measurement
        redo_aodm : bool, optional
          Redo the individual column density measurements (likely AODM)

        Returns
        -------
        None
          Fills the component attributes instead
        """
        # Check
        if (self.flag_N != 0) and (not overwrite):
            raise IOError("Column densities already set.  Use overwrite=True to redo.")
        # Redo?
        if redo_aodm:
            for aline in self._abslines:
                aline.measure_aodm(**kwargs)
        # Collate
        self.flag_N = 0
        for aline in self._abslines:
            if aline.attrib['flag_N'] == 0:  # No value
                warnings.warn("Absline {} has flag=0.  Hopefully you expected that".format(str(aline)))
                continue
            # Check N is filled
            if np.allclose(aline.attrib['N'].value, 0.):
                raise ValueError("Need to set N in attrib.  \n Consider linear_clm in linetools.analysis.absline")
            if aline.attrib['flag_N'] == 1:  # Good value?
                if self.flag_N == 1:  # Weighted mean
                    # Original
                    weight = 1. / self.sig_N**2
                    mu = self.N * weight
                    # Update
                    weight += 1./aline.attrib['sig_N']**2
                    self.N = (mu + aline.attrib['N']/aline.attrib['sig_N']**2) / weight
                    self.sig_N = np.sqrt(1./weight)
                else:  # Fill
                    self.N = aline.attrib['N']
                    self.sig_N = aline.attrib['sig_N']
                    self.flag_N = 1
            elif aline.attrib['flag_N'] == 2:  # Lower limit
                if self.flag_N in [0, 3]:
                    self.N = aline.attrib['N']
                    self.sig_N = aline.attrib['sig_N']
                    self.flag_N = 2
                elif self.flag_N == 2:
                    if aline.attrib['N'] > self.N:
                        self.N = aline.attrib['N']
                        self.sig_N = aline.attrib['sig_N']
                elif self.flag_N == 1:
                    pass
            elif aline.attrib['flag_N'] == 3:  # Upper limit
                if self.flag_N == 0:
                    self.N = aline.attrib['N']
                    self.sig_N = aline.attrib['sig_N']
                    self.flag_N = 3
                elif self.flag_N in [1, 2]:
                    pass
                elif self.flag_N == 3:
                    if aline.attrib['N'] < self.N:
                        self.N = aline.attrib['N']
                        self.sig_N = aline.attrib['sig_N']
            elif aline.attrib['flag_N'] == 0:  # No value
                warnings.warn("Absline {} has flag=0.  Hopefully you expected that")
            else:
                raise ValueError("Bad flag_N value")
        # Log values
        if self.flag_N > 0:
            self.logN, self.sig_logN = ltaa.log_clm(self)
Exemplo n.º 5
0
    def from_abslines(cls,
                      abslines,
                      stars=None,
                      comment="",
                      reliability='none',
                      skip_synth=False,
                      adopt_median=False,
                      tol=0.01,
                      chk_meas=False,
                      verbose=True,
                      **kwargs):
        """Instantiate from a list of AbsLine objects
        If the AbsLine objects contain column density measurements,
        these will be synthesized in one of two ways (controlled by adopt_median)

        Parameters
        ----------
        abslines : list 
            List of AbsLine objects
        stars : str, optional
            Asterisks to append to the ion name (e.g. fine-structure, CII*)
        comment : str
            A comment associated to the resulting AbsComponent
            Default is `""`
        reliability : str, optional
            Reliability of AbsComponent
                'a' - reliable
                'b' - possible
                'c' - uncertain
                'none' - not defined (default)
        skip_synth : bool, optional
            Skip synthesizing the column densities (and more) of the AbsLine objects
        adopt_median : bool, optional
            Adopt median values for N, b, vel from the AbsLine objects
            Otherwise, use synthesize_colm for the column densities
        chk_meas : bool, optional
            If true, require that measurements for lines composing a component
            have matching values before setting component attribs.
            Otherwise, throw a warning
        tol : float, optional
            Fractional tolerance for line attributes (N,b) to match one another
            Only applied if chk_meas=True and adopt_median=True
        **kwargs -- Passed to add_absline

        """
        from linetools.analysis import absline as ltaa
        # Check
        if not isinstance(abslines, list):
            raise IOError("Need a list of AbsLine objects")
        if not all(isinstance(x, AbsLine) for x in abslines):
            raise IOError("List needs to contain only AbsLine objects")

        # Instantiate with the first line
        init_line = abslines[0]
        slf = cls(init_line.attrib['coord'],
                  (init_line.data['Z'], init_line.data['ion']),
                  init_line.z,
                  init_line.limits.vlim,
                  Ej=init_line.data['Ej'],
                  stars=stars,
                  reliability=reliability,
                  comment=comment)
        slf._abslines.append(init_line)

        # Append with component checking
        if len(abslines) > 1:
            for absline in abslines[1:]:
                slf.add_absline(absline, **kwargs)

        ### Synthesize column density (and more)
        if not skip_synth:
            if not adopt_median:
                slf.synthesize_colm(**kwargs)
            else:
                # First check that the measurements for all the lines match
                # Grab them all
                cols = np.array([al.attrib['N'].value for al in abslines])
                colerrs = np.array(
                    [al.attrib['sig_N'].value for al in abslines])
                bs = np.array([al.attrib['b'].value for al in abslines])
                berrs = np.array([al.attrib['sig_b'].value for al in abslines])
                vels = np.array([al.attrib['vel'].value for al in abslines])
                velerrs = np.array(
                    [al.attrib['sig_vel'].value for al in abslines])
                medcol = np.median(cols)
                medcolerr = np.median(colerrs, axis=0)
                medb = np.median(bs)
                medberr = np.median(berrs)
                medvel = np.median(vels)
                medvelerr = np.median(velerrs)
                # Perform checks on measurements
                if medcol == 0.:
                    colcrit = np.all((cols) == 0.)
                else:
                    colcrit = all(np.abs(cols - medcol) / medcol < tol) is True
                if medb == 0.:
                    bcrit = np.all((bs) == 0.)
                else:
                    bcrit = all(np.abs(bs - medb) / medb < tol) is True
                # Assign appropriate flag
                flags = np.array([al.attrib['flag_N'] for al in abslines])
                if 1 in flags:  # Any of the lines is detected and unsaturated
                    slf.attrib['flag_N'] = 1
                elif np.all(flags == 3):  # All of the lines are upper limits
                    slf.attrib['flag_N'] = 3
                elif 2 in flags:  # Any of the lines is saturated
                    slf.attrib['flag_N'] = 2
                elif np.all(
                        flags == 0):  # Something else, e.g., line not covered
                    slf.attrib['flag_N'] = 0
                else:
                    raise ValueError("AbsLine flag_N values conflict. Cannot"
                                     " instantiate AbsComponent.")

                # Set attribs
                slf.attrib['N'] = medcol / u.cm**2
                slf.attrib['sig_N'] = medcolerr / u.cm**2
                slf.attrib['b'] = medb * u.km / u.s
                slf.attrib['sig_b'] = medberr * u.km / u.s
                slf.attrib['vel'] = medvel * u.km / u.s
                slf.attrib['sig_vel'] = medvelerr * u.km / u.s
                logN, sig_logN = ltaa.log_clm(slf.attrib)
                slf.attrib['logN'] = logN
                slf.attrib['sig_logN'] = sig_logN
                # Stop or throw warnings
                if (bcrit & colcrit):
                    pass
                else:
                    if verbose or chk_meas:
                        if bcrit:
                            print(
                                'A problem lies in the column density values')
                        elif colcrit:
                            print('A problem lies in the b values')
                        else:
                            print(
                                'Problems lie in the column densities and b values'
                            )
                        if chk_meas:
                            raise ValueError(
                                'The line measurements for the lines in this '
                                'component are not consistent with one another.'
                            )
                        else:
                            warnings.warn(
                                'The line measurements for the lines in this component'
                                ' may not be consistent with one another.')
        # Return
        return slf
Exemplo n.º 6
0
    def synthesize_colm(self,
                        overwrite=False,
                        redo_aodm=False,
                        debug=False,
                        **kwargs):
        """Synthesize column density measurements of the component.
        Default is to use the current AbsLine values, but the user can
        request that those be re-calculated with AODM.

        Currently, the weighted mean is performed by taking the average
        error given in sig_N which is a 2-element array.

        Parameters
        ----------
        overwrite : bool, optional
          Clobber any previous measurement
        redo_aodm : bool, optional
          Redo the individual column density measurements (likely AODM)

        Returns
        -------
        None
          Fills the component attributes instead
        """
        # Check
        if (self.flag_N != 0) and (not overwrite):
            raise IOError(
                "Column densities already set.  Use overwrite=True to redo.")
        # Redo?
        if redo_aodm:
            for aline in self._abslines:
                aline.measure_aodm(**kwargs)
        # Collate
        self.attrib['flag_N'] = 0
        if debug:
            pdb.set_trace()
        for aline in self._abslines:
            if aline.attrib['flag_N'] == 0:  # No value
                warnings.warn(
                    "Absline {} has flag=0.  Hopefully you expected that".
                    format(str(aline)))
                continue
            # Check N is filled
            if np.isclose(aline.attrib['N'].value, 0.):
                raise ValueError(
                    "Need to set N in attrib.  \n Consider linear_clm in linetools.analysis.absline"
                )
            if aline.attrib['flag_N'] == 1:  # Good value?
                if self.flag_N == 1:  # Weighted mean
                    # Original
                    weight = 1. / np.mean(self.sig_N)**2
                    mu = self.N * weight
                    # Update
                    weight += 1. / np.mean(aline.attrib['sig_N'])**2
                    self.attrib['N'] = (mu + aline.attrib['N'] / np.mean(
                        aline.attrib['sig_N'])**2) / weight
                    self.attrib['sig_N'] = Quantity([np.sqrt(1. / weight)] * 2)
                else:  # Fill
                    self.attrib['N'] = aline.attrib['N']
                    self.attrib['sig_N'] = aline.attrib['sig_N']
                    self.attrib['flag_N'] = 1
            elif aline.attrib['flag_N'] == 2:  # Lower limit
                if self.flag_N in [0, 3]:
                    self.attrib['N'] = aline.attrib['N']
                    self.attrib['sig_N'] = aline.attrib['sig_N']
                    self.attrib['flag_N'] = 2
                elif self.flag_N == 2:
                    if aline.attrib['N'] > self.N:
                        self.attrib['N'] = aline.attrib['N']
                        self.attrib['sig_N'] = aline.attrib['sig_N']
                elif self.flag_N == 1:
                    pass
            elif aline.attrib['flag_N'] == 3:  # Upper limit
                if self.flag_N == 0:
                    self.attrib['N'] = aline.attrib['N']
                    self.attrib['sig_N'] = aline.attrib['sig_N']
                    self.attrib['flag_N'] = 3
                elif self.flag_N in [1, 2]:
                    pass
                elif self.flag_N == 3:
                    if aline.attrib['N'] < self.N:
                        self.attrib['N'] = aline.attrib['N']
                        self.attrib['sig_N'] = aline.attrib['sig_N']
            elif aline.attrib['flag_N'] == 0:  # No value
                warnings.warn(
                    "Absline {} has flag=0.  Hopefully you expected that")
            else:
                raise ValueError("Bad flag_N value")
        # Enforce 2-element error arrays
        if self.attrib['sig_N'].size == 1:
            self.attrib['sig_N'] = [self.attrib['sig_N'].value
                                    ] * 2 * self.attrib['sig_N'].unit
        # Log values
        if self.flag_N > 0:
            _, _ = ltaa.log_clm(self.attrib)
Exemplo n.º 7
0
    def synthesize_colm(self, overwrite=False, redo_aodm=False, **kwargs):
        """Synthesize column density measurements of the component.
        Default is to use the current AbsLine values, but the user can
        request that those be re-calculated with AODM

        Parameters
        ----------
        overwrite : bool, optional
          Clobber any previous measurement
        redo_aodm : bool, optional
          Redo the individual column density measurements (likely AODM)

        Returns
        -------
        None
          Fills the component attributes instead
        """
        # Check
        if (self.flgN != 0) and (not overwrite):
            raise IOError("Column densities already set.  Use clobber=True to redo.")
        # Redo?
        if redo_aodm:
            for aline in self._abslines:
                aline.measure_aodm(**kwargs)
        # Collate
        self.flgN = 0
        for aline in self._abslines:
            if aline.attrib['flagN'] == 1: # Good value?
                if self.flgN == 1: # Weighted mean
                    # Original
                    weight = 1. / self.sigN**2
                    mu= self.N * weight
                    # Update
                    weight += 1./aline.attrib['sigN']**2
                    self.N = (mu + aline.attrib['N']/aline.attrib['sigN']**2) / weight
                    self.sigN = np.sqrt(1./weight)
                else: # Fill
                    self.N = aline.attrib['N']
                    self.sigN = aline.attrib['sigN']
                    self.flgN = 1
            elif aline.attrib['flagN'] == 2: # Lower limit
                if self.flgN in [0,3]:
                    self.N = aline.attrib['N']
                    self.sigN = 99.
                    self.flgN = 2
                elif self.flgN == 2:
                    self.N = max(self.N,aline.attrib['N'])
                    self.sigN = 99.
                elif self.flgN == 1:
                    pass
            elif aline.attrib['flagN'] == 3: # Upper limit
                if self.flgN == 0:
                    self.N = aline.attrib['N']
                    self.sigN = aline.attrib['sigN']
                    self.flgN = 3
                elif self.flgN in [1,2]:
                    pass
                elif self.flgN == 3:
                    if aline.attrib['N'] < self.N:
                        self.N = aline.attrib['N']
                        self.sigN = aline.attrib['sigN']
            else:
                raise ValueError("Bad flagN value")
        # Log values
        self.logN, self.sig_logN = ltaa.log_clm(self)
Exemplo n.º 8
0
def test_logclm():
    obj = type(str('Dummy'), (object,), { str('N'): 1e13, str('sig_N'): 5e12 })
    #
    logN, sig_logN = log_clm(obj)
    np.testing.assert_allclose(logN, 13.)
Exemplo n.º 9
0
    def from_abslines(cls, abslines, stars=None, comment="", reliability='none',
                      skip_synth=False,
                      adopt_median=False, tol=0.01, chk_meas=False, verbose=True, **kwargs):
        """Instantiate from a list of AbsLine objects
        If the AbsLine objects contain column density measurements,
        these will be synthesized in one of two ways (controlled by adopt_median)

        Parameters
        ----------
        abslines : list 
            List of AbsLine objects
        stars : str, optional
            Asterisks to append to the ion name (e.g. fine-structure, CII*)
        comment : str
            A comment associated to the resulting AbsComponent
            Default is `""`
        reliability : str, optional
            Reliability of AbsComponent
                'a' - reliable
                'b' - possible
                'c' - uncertain
                'none' - not defined (default)
        skip_synth : bool, optional
            Skip synthesizing the column densities (and more) of the AbsLine objects
        adopt_median : bool, optional
            Adopt median values for N, b, vel from the AbsLine objects
            Otherwise, use synthesize_colm for the column densities
        chk_meas : bool, optional
            If true, require that measurements for lines composing a component
            have matching values before setting component attribs.
            Otherwise, throw a warning
        tol : float, optional
            Fractional tolerance for line attributes (N,b) to match one another
            Only applied if chk_meas=True and adopt_median=True
        **kwargs -- Passed to add_absline

        """
        from linetools.analysis import absline as ltaa
        # Check
        if not isinstance(abslines, list):
            raise IOError("Need a list of AbsLine objects")
        if not all(isinstance(x, AbsLine) for x in abslines):
            raise IOError("List needs to contain only AbsLine objects")

        # Instantiate with the first line
        init_line = abslines[0]
        slf = cls( init_line.attrib['coord'], (init_line.data['Z'],init_line.data['ion']),
                   init_line.z, init_line.limits.vlim,
                   Ej=init_line.data['Ej'], stars=stars, reliability=reliability, comment=comment)
        slf._abslines.append(init_line)

        # Append with component checking
        if len(abslines) > 1:
            for absline in abslines[1:]:
                slf.add_absline(absline, **kwargs)

        ### Synthesize column density (and more)
        if not skip_synth:
            if not adopt_median:
                slf.synthesize_colm(**kwargs)
            else:
                # First check that the measurements for all the lines match
                # Grab them all
                cols = np.array([al.attrib['N'].value for al in abslines])
                colerrs = np.array([al.attrib['sig_N'].value for al in abslines])
                bs = np.array([al.attrib['b'].value for al in abslines])
                berrs = np.array([al.attrib['sig_b'].value for al in abslines])
                vels = np.array([al.attrib['vel'].value for al in abslines])
                velerrs = np.array([al.attrib['sig_vel'].value for al in abslines])
                medcol = np.median(cols)
                medcolerr = np.median(colerrs, axis=0)
                medb = np.median(bs)
                medberr = np.median(berrs)
                medvel = np.median(vels)
                medvelerr = np.median(velerrs)
                # Perform checks on measurements
                if medcol == 0.:
                    colcrit = np.all((cols) == 0.)
                else:
                    colcrit = all(np.abs(cols - medcol) / medcol < tol) is True
                if medb == 0.:
                    bcrit = np.all((bs) == 0.)
                else:
                    bcrit = all(np.abs(bs - medb) / medb < tol) is True
                # Assign appropriate flag
                flags = np.array([al.attrib['flag_N'] for al in abslines])
                if 1 in flags:  # Any of the lines is detected and unsaturated
                    slf.attrib['flag_N'] = 1
                elif np.all(flags == 3):  # All of the lines are upper limits
                    slf.attrib['flag_N'] = 3
                elif 2 in flags:  # Any of the lines is saturated
                    slf.attrib['flag_N'] = 2
                elif np.all(flags == 0):  # Something else, e.g., line not covered
                    slf.attrib['flag_N'] = 0
                else:
                    raise ValueError("AbsLine flag_N values conflict. Cannot"
                                     " instantiate AbsComponent.")

                # Set attribs
                slf.attrib['N'] = medcol / u.cm ** 2
                slf.attrib['sig_N'] = medcolerr / u.cm ** 2
                slf.attrib['b'] = medb * u.km / u.s
                slf.attrib['sig_b'] = medberr * u.km / u.s
                slf.attrib['vel'] = medvel * u.km / u.s
                slf.attrib['sig_vel'] = medvelerr * u.km / u.s
                logN, sig_logN = ltaa.log_clm(slf.attrib)
                slf.attrib['logN'] = logN
                slf.attrib['sig_logN'] = sig_logN
                # Stop or throw warnings
                if (bcrit&colcrit):
                    pass
                else:
                    if verbose or chk_meas:
                        if bcrit:
                            print('A problem lies in the column density values')
                        elif colcrit:
                            print('A problem lies in the b values')
                        else:
                            print('Problems lie in the column densities and b values')
                        if chk_meas:
                            raise ValueError('The line measurements for the lines in this '
                                         'component are not consistent with one another.')
                        else:
                            warnings.warn('The line measurements for the lines in this component'
                                      ' may not be consistent with one another.')
        # Return
        return slf
Exemplo n.º 10
0
    def synthesize_colm(self, overwrite=False, redo_aodm=False, debug=False, **kwargs):
        """Synthesize column density measurements of the component.
        Default is to use the current AbsLine values, but the user can
        request that those be re-calculated with AODM.

        Currently, the weighted mean is performed by taking the average
        error given in sig_N which is a 2-element array.

        Parameters
        ----------
        overwrite : bool, optional
          Clobber any previous measurement
        redo_aodm : bool, optional
          Redo the individual column density measurements (likely AODM)

        Returns
        -------
        None
          Fills the component attributes instead
        """
        # Check
        if (self.flag_N != 0) and (not overwrite):
            raise IOError("Column densities already set.  Use overwrite=True to redo.")
        # Redo?
        if redo_aodm:
            for aline in self._abslines:
                aline.measure_aodm(**kwargs)
        # Collate
        self.attrib['flag_N'] = 0
        if debug:
            pdb.set_trace()
        for aline in self._abslines:
            if aline.attrib['flag_N'] == 0:  # No value
                warnings.warn("Absline {} has flag=0.  Hopefully you expected that".format(str(aline)))
                continue
            # Check N is filled
            if np.isclose(aline.attrib['N'].value, 0.):
                raise ValueError("Need to set N in attrib.  \n Consider linear_clm in linetools.analysis.absline")
            if aline.attrib['flag_N'] == 1:  # Good value?
                if self.flag_N == 1:  # Weighted mean
                    # Original
                    weight = 1. / np.mean(self.sig_N)**2
                    mu = self.N * weight
                    # Update
                    weight += 1./np.mean(aline.attrib['sig_N'])**2
                    self.attrib['N'] = (mu + aline.attrib['N']/np.mean(aline.attrib['sig_N'])**2) / weight
                    self.attrib['sig_N'] = Quantity([np.sqrt(1./weight)]*2)
                else:  # Fill
                    self.attrib['N'] = aline.attrib['N']
                    self.attrib['sig_N'] = aline.attrib['sig_N']
                    self.attrib['flag_N'] = 1
            elif aline.attrib['flag_N'] == 2:  # Lower limit
                if self.flag_N in [0, 3]:
                    self.attrib['N'] = aline.attrib['N']
                    self.attrib['sig_N'] = aline.attrib['sig_N']
                    self.attrib['flag_N'] = 2
                elif self.flag_N == 2:
                    if aline.attrib['N'] > self.N:
                        self.attrib['N'] = aline.attrib['N']
                        self.attrib['sig_N'] = aline.attrib['sig_N']
                elif self.flag_N == 1:
                    pass
            elif aline.attrib['flag_N'] == 3:  # Upper limit
                if self.flag_N == 0:
                    self.attrib['N'] = aline.attrib['N']
                    self.attrib['sig_N'] = aline.attrib['sig_N']
                    self.attrib['flag_N'] = 3
                elif self.flag_N in [1, 2]:
                    pass
                elif self.flag_N == 3:
                    if aline.attrib['N'] < self.N:
                        self.attrib['N'] = aline.attrib['N']
                        self.attrib['sig_N'] = aline.attrib['sig_N']
            elif aline.attrib['flag_N'] == 0:  # No value
                warnings.warn("Absline {} has flag=0.  Hopefully you expected that")
            else:
                raise ValueError("Bad flag_N value")
        # Enforce 2-element error arrays
        if self.attrib['sig_N'].size == 1:
            self.attrib['sig_N'] = [self.attrib['sig_N'].value]*2 * self.attrib['sig_N'].unit
        # Log values
        if self.flag_N > 0:
            _, _ = ltaa.log_clm(self.attrib)
Exemplo n.º 11
0
    def synthesize_colm(self, overwrite=False, redo_aodm=False, **kwargs):
        """Synthesize column density measurements of the component.
        Default is to use the current AbsLine values, but the user can
        request that those be re-calculated with AODM.

        Parameters
        ----------
        overwrite : bool, optional
          Clobber any previous measurement
        redo_aodm : bool, optional
          Redo the individual column density measurements (likely AODM)

        Returns
        -------
        None
          Fills the component attributes instead
        """
        # Check
        if (self.flag_N != 0) and (not overwrite):
            raise IOError(
                "Column densities already set.  Use overwrite=True to redo.")
        # Redo?
        if redo_aodm:
            for aline in self._abslines:
                aline.measure_aodm(**kwargs)
        # Collate
        self.flag_N = 0
        for aline in self._abslines:
            if aline.attrib['flag_N'] == 0:  # No value
                warnings.warn(
                    "Absline {} has flag=0.  Hopefully you expected that".
                    format(str(aline)))
                continue
            # Check N is filled
            if np.allclose(aline.attrib['N'].value, 0.):
                raise ValueError(
                    "Need to set N in attrib.  \n Consider linear_clm in linetools.analysis.absline"
                )
            if aline.attrib['flag_N'] == 1:  # Good value?
                if self.flag_N == 1:  # Weighted mean
                    # Original
                    weight = 1. / self.sig_N**2
                    mu = self.N * weight
                    # Update
                    weight += 1. / aline.attrib['sig_N']**2
                    self.N = (mu + aline.attrib['N'] /
                              aline.attrib['sig_N']**2) / weight
                    self.sig_N = np.sqrt(1. / weight)
                else:  # Fill
                    self.N = aline.attrib['N']
                    self.sig_N = aline.attrib['sig_N']
                    self.flag_N = 1
            elif aline.attrib['flag_N'] == 2:  # Lower limit
                if self.flag_N in [0, 3]:
                    self.N = aline.attrib['N']
                    self.sig_N = aline.attrib['sig_N']
                    self.flag_N = 2
                elif self.flag_N == 2:
                    if aline.attrib['N'] > self.N:
                        self.N = aline.attrib['N']
                        self.sig_N = aline.attrib['sig_N']
                elif self.flag_N == 1:
                    pass
            elif aline.attrib['flag_N'] == 3:  # Upper limit
                if self.flag_N == 0:
                    self.N = aline.attrib['N']
                    self.sig_N = aline.attrib['sig_N']
                    self.flag_N = 3
                elif self.flag_N in [1, 2]:
                    pass
                elif self.flag_N == 3:
                    if aline.attrib['N'] < self.N:
                        self.N = aline.attrib['N']
                        self.sig_N = aline.attrib['sig_N']
            elif aline.attrib['flag_N'] == 0:  # No value
                warnings.warn(
                    "Absline {} has flag=0.  Hopefully you expected that")
            else:
                raise ValueError("Bad flag_N value")
        # Log values
        if self.flag_N > 0:
            self.logN, self.sig_logN = ltaa.log_clm(self)
Exemplo n.º 12
0
def test_logclm():
    obj = type(str('Dummy'), (object, ), {str('N'): 1e13, str('sig_N'): 5e12})
    #
    logN, sig_logN = log_clm(obj)
    np.testing.assert_allclose(logN, 13.)