Ejemplo n.º 1
0
    def _add_levels(self, df):

        viblvl_label = self.viblvl_label

        if viblvl_label == "p":
            df["viblvl"] = vib_lvl_name_cdsd_p(df.p,)
        elif viblvl_label == "pc":
            df["viblvl"] = vib_lvl_name_cdsd_pc(df.p, df.c)
        elif viblvl_label == "pcN":
            df["viblvl"] = vib_lvl_name_cdsd_pcN(df.p, df.c, df.N)
        elif viblvl_label == "pcJN":
            df["viblvl"] = vib_lvl_name_cdsd_pcJN(df.p, df.c, df.j, df.N)
        elif viblvl_label is None:
            # dont label the levels. Wont be able to use the EnergyDatabase to fetch
            # vibrational energies for lines, however it can still be used to
            # calculate Partition functions independently from a Spectrum calculation
            pass
        else:
            raise ValueError("Unexpected viblvl_label value: {0}".format(viblvl_label))

        return df
Ejemplo n.º 2
0
def add_bands(df, dbformat, lvlformat, verbose=True):
    ''' Assign all transitions to a vibrational band:

    Add 'band', 'viblvl_l' and 'viblvl_u' attributes for each line to allow 
    parsing the lines by band with::

        df0.groupby('band')

    Parameters
    ----------

    df: pandas Dataframe
        Line (transitions) database

    dbformat: one of :data:`~radis.lbl.loader.KNOWN_DBFORMAT` : ``'cdsd```, ``'hitemp'``
        format of Line database

    lvlformat: 'cdsd`, 'hitemp'
        format of 

    Returns
    -------

    None
        input df is changed

    Examples
    --------

    Add transitions in a Dataframe based on CDSD (p, c, j, n) format::

        add_bands(df, 'cdsd')

    Notes
    -----

    Performance with test case (CDSD CO2 2380-2400 cm-1):

    - Initial: with .apply()   8.08 s ± 95.2 ms
    - with groupby(): 9s   worse!!
    - using simple (and more readable)    astype(str)  statements: 523 ms ± 19.6 ms

    '''

    # Check inputs
    if not dbformat in KNOWN_DBFORMAT:
        raise ValueError('dbformat ({0}) should be one of: {1}'.format(
            dbformat, KNOWN_DBFORMAT))
    if not lvlformat in KNOWN_LVLFORMAT:
        raise ValueError('lvlformat ({0}) should be one of: {1}'.format(
            lvlformat, KNOWN_LVLFORMAT))

    if verbose:
        t0 = time()
        print('... sorting lines by vibrational bands')

    # Calculate bands:
    id = list(pd.unique(df['id']))
    if len(id) > 1:
        raise ValueError('Cant calculate vibrational bands for multiple ' +
                         'molecules yet')  # although it's an easy fix. Just
        # groupby id
    molecule = get_molecule(id[0])

    if molecule == 'CO2':

        vib_lvl_name_hitran = vib_lvl_name_hitran_class5

        if lvlformat in ['cdsd-pc', 'cdsd-pcN', 'cdsd-hamil']:

            # ensures that vib_lvl_name functions wont crash
            if dbformat not in ['cdsd', 'cdsd4000', 'hitran']:
                raise NotImplementedError(
                    'lvlformat {0} not supported with dbformat {1}'.format(
                        lvlformat, dbformat))

            # Use vibrational nomenclature of CDSD (p,c,j,n) or HITRAN (v1v2l2v3J)
            # depending on the Level Database.
            # In both cases, store the other one.

            # ... note: vib level in a CDSD (p,c,j,n) database is ambiguous.
            # ... a vibrational energy Evib can have been defined for every (p, c) group:
            if lvlformat in ['cdsd-pc']:
                viblvl_l_cdsd = vib_lvl_name_cdsd_pc(df.polyl, df.wangl)
                viblvl_u_cdsd = vib_lvl_name_cdsd_pc(df.polyu, df.wangu)
            # ... or for every (p, c, N) group:
            elif lvlformat in ['cdsd-pcN']:
                viblvl_l_cdsd = vib_lvl_name_cdsd_pcN(df.polyl, df.wangl,
                                                      df.rankl)
                viblvl_u_cdsd = vib_lvl_name_cdsd_pcN(df.polyu, df.wangu,
                                                      df.ranku)
            # ... or for every level (p, c, J ,N)  (that's the case if coupling terms
            # are used taken into account... it also takes a much longer time
            # to look up vibrational energies in the LineDatabase, warning!):
            elif lvlformat in ['cdsd-hamil']:
                viblvl_l_cdsd = vib_lvl_name_cdsd_pcJN(df.polyl, df.wangl,
                                                       df.jl, df.rankl)
                viblvl_u_cdsd = vib_lvl_name_cdsd_pcJN(df.polyu, df.wangu,
                                                       df.ju, df.ranku)
            else:
                raise ValueError(
                    'Unexpected level format: {0}'.format(lvlformat))

            band_cdsd = viblvl_l_cdsd + '->' + viblvl_u_cdsd

            df.loc[:, 'viblvl_l'] = viblvl_l_cdsd
            df.loc[:, 'viblvl_u'] = viblvl_u_cdsd
            df.loc[:, 'band'] = band_cdsd

            # Calculate HITRAN format too (to store them))
            if all_in(['v1l', 'v2l', 'l2l', 'v3l'], df):
                viblvl_l_hitran = vib_lvl_name_hitran(df.v1l, df.v2l, df.l2l,
                                                      df.v3l)
                viblvl_u_hitran = vib_lvl_name_hitran(df.v1u, df.v2u, df.l2u,
                                                      df.v3u)
                band_hitran = viblvl_l_hitran + '->' + viblvl_u_hitran

                df.loc[:, 'viblvl_htrn_l'] = viblvl_l_hitran
                df.loc[:, 'viblvl_htrn_u'] = viblvl_u_hitran
                df.loc[:, 'band_htrn'] = band_hitran

        # 'radis' uses Dunham development based on v1v2l2v3 HITRAN convention
        elif lvlformat in ['radis']:

            if dbformat not in ['hitran', 'cdsd']:
                raise NotImplementedError(
                    'lvlformat `{0}` not supported with dbformat `{1}`'.format(
                        lvlformat, dbformat))

            # Calculate bands with HITRAN convention
            viblvl_l_hitran = vib_lvl_name_hitran(df.v1l, df.v2l, df.l2l,
                                                  df.v3l)
            viblvl_u_hitran = vib_lvl_name_hitran(df.v1u, df.v2u, df.l2u,
                                                  df.v3u)
            band_hitran = viblvl_l_hitran + '->' + viblvl_u_hitran

            df.loc[:, 'viblvl_l'] = viblvl_l_hitran
            df.loc[:, 'viblvl_u'] = viblvl_u_hitran
            df.loc[:, 'band'] = band_hitran

        else:
            raise NotImplementedError(
                'Cant deal with lvlformat={0} for {1}'.format(
                    lvlformat, molecule))

    elif molecule in HITRAN_CLASS1:  # includes 'CO'
        # Note. TODO. Move that in loader.py (or somewhere consistent with
        # classes defined in cdsd.py / hitran.py)

        if lvlformat in ['radis']:

            # ensures that vib_lvl_name functions wont crash
            if dbformat not in ['hitran']:
                raise NotImplementedError(
                    'lvlformat {0} not supported with dbformat {1}'.format(
                        lvlformat, dbformat))

            vib_lvl_name = vib_lvl_name_hitran_class1

            df.loc[:, 'viblvl_l'] = vib_lvl_name(df['vl'])
            df.loc[:, 'viblvl_u'] = vib_lvl_name(df['vu'])
            df.loc[:, 'band'] = df['viblvl_l'] + '->' + df['viblvl_u']

        else:
            raise NotImplementedError(
                'Lvlformat not defined for {0}: {1}'.format(
                    molecule, lvlformat))

    else:
        raise NotImplementedError(
            'Vibrational bands not yet defined for molecule: ' +
            '{0} with database format: {1}. '.format(molecule, dbformat) +
            'Update add_bands()')

    if verbose:
        print(('... lines sorted in {0:.1f}s'.format(time() - t0)))

    return