Skip to content

Register LaTeX reader for Cosmology #14837

Open

Description

@nstarman

What is the problem this feature will solve?

A reader for the Cosmology -> LaTeX (-> Cosmology)

Describe the desired outcome

No response

Additional context

Following up on #14701, thanks @Mubin17!

Activity

  1. added this to the v6.0 milestone on May 17, 2023
  2. nstarman commented on May 17, 2023

    @nstarman
    MemberAuthor

    @Mubin17, right of refusal is yours 😆.

  3. pllim commented on May 17, 2023

    @pllim
    Member

    We usually don't milestone issues. Will this block 6.0 release or something?

  4. nstarman commented on May 17, 2023

    @nstarman
    MemberAuthor

    Not strictly, but it should be in by then. I want read/write for LaTeX by 6.0.

  5. Mubin17 commented on May 17, 2023

    @Mubin17
    Contributor

    @nstarman Before I create a PR. While working on write_latex(), I came up with the following code for read_latex() based on the structure of read_html_table():

    def read_latex(filename, index=None, *, move_to_meta=False, cosmology=None,**kwargs):
        format = kwargs.pop("format", "latex")
        if format != "latex":
            raise ValueError(f"format must be 'latex', not {format}")
        
        with u.add_enabled_units(cu):
            table = QTable.read(filename, format="latex", **kwargs)
    
        table_columns = set(table.colnames)
        for name, latex in _FORMAT_TABLE.items():
            if latex in table_columns:
                table.rename_column(latex, name)
                
        # Build the cosmology from table, using the private backend.
        return from_table(table, index=index, move_to_meta=move_to_meta, cosmology=cosmology)

    However, upon execution, it throws this error:

    ValueError: '.. 0.06' did not parse as unit: Syntax error parsing unit '.. 0.06' 
    If this is meant to be a custom unit, define it with 'u.def_unit'. 
    To have it recognized inside a file reader or other code, enable it with 'u.add_enabled_units'. 
    For details, see https://docs.astropy.org/en/latest/units/combining_and_defining.html
    

    Do you have any suggestions on how can I tackle this error?

  6. nstarman commented on May 18, 2023

    @nstarman
    MemberAuthor

    Do you recall which line is throwing this error? Is it table = QTable.read(filename, format="latex", **kwargs)?

  7. Mubin17 commented on May 18, 2023

    @Mubin17
    Contributor

    @nstarman I believe it is the following line return from_table(table, index=index, move_to_meta=move_to_meta, cosmology=cosmology). For further clarification I have put the entire error message below:


    ValueError                                Traceback (most recent call last)
    File ~/opt/anaconda3/envs/Astropy_Playground/lib/python3.10/site-packages/astropy/units/format/generic.py:613, in Generic._do_parse(cls, s, debug)
        610 try:
        611     # This is a short circuit for the case where the string
        612     # is just a single unit name
    --> 613     return cls._parse_unit(s, detailed_exception=False)
        614 except ValueError as e:
    
    File ~/opt/anaconda3/envs/Astropy_Playground/lib/python3.10/site-packages/astropy/units/format/generic.py:512, in 
    Generic._parse_unit(cls, s, detailed_exception)
        511 else:
    --> 512     raise ValueError()
    
    ValueError: 
    
    During handling of the above exception, another exception occurred:
    
    ValueError                                Traceback (most recent call last)
    File ~/opt/anaconda3/envs/Astropy_Playground/lib/python3.10/site-packages/astropy/units/format/generic.py:616, in 
    Generic._do_parse(cls, s, debug)
        615 try:
    --> 616     return cls._parser.parse(s, lexer=cls._lexer, debug=debug)
        617 except ValueError as e:
    
    File ~/opt/anaconda3/envs/Astropy_Playground/lib/python3.10/site-packages/astropy/utils/parsing.py:115, in 
    ThreadSafeParser.parse(self, *args, **kwargs)
        114 with self._lock:
    --> 115     return self.parser.parse(*args, **kwargs)
    
    File ~/opt/anaconda3/envs/Astropy_Playground/lib/python3.10/site-packages/astropy/extern/ply/yacc.py:333, in 
    LRParser.parse(self, input, lexer, debug, tracking, tokenfunc)
        332 else:
    --> 333     return self.parseopt_notrack(input, lexer, debug, tracking, tokenfunc)
    
    File ~/opt/anaconda3/envs/Astropy_Playground/lib/python3.10/site-packages/astropy/extern/ply/yacc.py:1201, in 
    LRParser.parseopt_notrack(self, input, lexer, debug, tracking, tokenfunc)
       1200 self.state = state
    -> 1201 tok = call_errorfunc(self.errorfunc, errtoken, self)
       1202 if self.errorok:
       1203     # User must have done some kind of panic
       1204     # mode recovery on their own.  The
       1205     # returned token is the next lookahead
    
    File ~/opt/anaconda3/envs/Astropy_Playground/lib/python3.10/site-packages/astropy/extern/ply/yacc.py:192, in 
    call_errorfunc(errorfunc, token, parser)
        191 _restart = parser.restart
    --> 192 r = errorfunc(token)
        193 try:
    
    File ~/opt/anaconda3/envs/Astropy_Playground/lib/python3.10/site-packages/astropy/units/format/generic.py:473, in 
    Generic._make_parser.<locals>.p_error(p)
        472 def p_error(p):
    --> 473     raise ValueError()
    
    ValueError: 
    
    During handling of the above exception, another exception occurred:
    
    ValueError                                Traceback (most recent call last)
    File ~/opt/anaconda3/envs/Astropy_Playground/lib/python3.10/site-packages/astropy/units/core.py:2018, in 
    _UnitMetaClass.__call__(self, s, represents, format, namespace, doc, parse_strict)
       2017 try:
    -> 2018     return f.parse(s)
       2019 except NotImplementedError:
    
    File ~/opt/anaconda3/envs/Astropy_Playground/lib/python3.10/site-packages/astropy/units/format/generic.py:598, in 
    Generic.parse(cls, s, debug)
        596     s = cls._regex_deg.sub(cls._convert_deg, s)
    --> 598 result = cls._do_parse(s, debug=debug)
        599 # Check for excess solidi, but exclude fractional exponents (accepted)
    
    File ~/opt/anaconda3/envs/Astropy_Playground/lib/python3.10/site-packages/astropy/units/format/generic.py:621, in 
    Generic._do_parse(cls, s, debug)
        620 else:
    --> 621     raise ValueError(f"Syntax error parsing unit '{s}'")
    
    ValueError: Syntax error parsing unit '.. 0.06'
    
    During handling of the above exception, another exception occurred:
    
    ValueError                                Traceback (most recent call last)
    Cell In[4], line 1
    ----> 1 Cosmology.read("example_cosmology.tex",index=1, format="latex")
    
    File ~/opt/anaconda3/envs/Astropy_Playground/lib/python3.10/site-packages/astropy/cosmology/connect.py:81, in 
    CosmologyRead.__call__(self, *args, **kwargs)
         76         raise ValueError(
         77             "keyword argument `cosmology` must be either the class "
         78             f"{valid[0]} or its qualified name '{valid[1]}'")
         80 with add_enabled_units(cu):
    ---> 81     cosmo = self.registry.read(self._cls, *args, **kwargs)
         83 return cosmo
    
    File ~/opt/anaconda3/envs/Astropy_Playground/lib/python3.10/site-packages/astropy/io/registry/core.py:212, in 
    UnifiedInputRegistry.read(self, cls, format, cache, *args, **kwargs)
        208     format = self._get_valid_format(
        209         'read', cls, path, fileobj, args, kwargs)
        211 reader = self.get_reader(format, cls)
    --> 212 data = reader(*args, **kwargs)
        214 if not isinstance(data, cls):
        215     # User has read with a subclass where only the parent class is
        216     # registered.  This returns the parent class, so try coercing
        217     # to desired subclass.
        218     try:
    
    File ~/opt/anaconda3/envs/Astropy_Playground/lib/python3.10/site-packages/astropy/cosmology/io/latex.py:41, in 
    read_latex(filename, index, move_to_meta, cosmology, **kwargs)
         38         table.rename_column(latex, name)
         40 # Build the cosmology from table, using the private backend.
    ---> 41 return from_table(table, index=index, move_to_meta=move_to_meta, cosmology=cosmology)
    
    File ~/opt/anaconda3/envs/Astropy_Playground/lib/python3.10/site-packages/astropy/cosmology/io/table.py:136, in 
    from_table(table, index, move_to_meta, cosmology)
        133 row = table[index]  # index is now the row index (int)
        135 # parse row to cosmo
    --> 136 return from_row(row, move_to_meta=move_to_meta, cosmology=cosmology)
    
    File ~/opt/anaconda3/envs/Astropy_Playground/lib/python3.10/site-packages/astropy/cosmology/io/row.py:80, in 
    from_row(row, move_to_meta, cosmology)
         77 mapping["meta"] = dict(meta)
         79 # build cosmology from map
    ---> 80 return from_mapping(mapping, move_to_meta=move_to_meta, cosmology=cosmology)
    
    File ~/opt/anaconda3/envs/Astropy_Playground/lib/python3.10/site-packages/astropy/cosmology/io/mapping.py:114, in 
    from_mapping(map, move_to_meta, cosmology)
        111     raise TypeError(f"there are unused parameters {params}.")
        112 # else: pass  # no kwargs, no move-to-meta, and all the params are used
    --> 114 return cosmology(*ba.args, **ba.kwargs)
    
    File ~/opt/anaconda3/envs/Astropy_Playground/lib/python3.10/site-packages/astropy/cosmology/flrw/lambdacdm.py:616, in
     FlatLambdaCDM.__init__(self, H0, Om0, Tcmb0, Neff, m_nu, Ob0, name, meta)
        614 def __init__(self, H0, Om0, Tcmb0=0.0*u.K, Neff=3.04, m_nu=0.0*u.eV,
        615              Ob0=None, *, name=None, meta=None):
    --> 616     super().__init__(H0=H0, Om0=Om0, Ode0=0.0, Tcmb0=Tcmb0, Neff=Neff,
        617                      m_nu=m_nu, Ob0=Ob0, name=name, meta=meta)
        619     # Please see :ref:`astropy-cosmology-fast-integrals` for discussion
        620     # about what is being done here.
        621     if self._Tcmb0.value == 0:
    
    File ~/opt/anaconda3/envs/Astropy_Playground/lib/python3.10/site-packages/astropy/cosmology/flrw/base.py:1434, in 
    FlatFLRWMixin.__init__(self, *args, **kw)
       1433 def __init__(self, *args, **kw):
    -> 1434     super().__init__(*args, **kw)  # guaranteed not to have `Ode0`
       1435     # Do some twiddling after the fact to get flatness
       1436     self._Ok0 = 0.0
    
    File ~/opt/anaconda3/envs/Astropy_Playground/lib/python3.10/site-packages/astropy/cosmology/flrw/lambdacdm.py:91, in LambdaCDM.__init__(self, H0, Om0, Ode0, Tcmb0, Neff, m_nu, Ob0, name, meta)
         89 def __init__(self, H0, Om0, Ode0, Tcmb0=0.0*u.K, Neff=3.04, m_nu=0.0*u.eV,
         90              Ob0=None, *, name=None, meta=None):
    ---> 91     super().__init__(H0=H0, Om0=Om0, Ode0=Ode0, Tcmb0=Tcmb0, Neff=Neff,
         92                      m_nu=m_nu, Ob0=Ob0, name=name, meta=meta)
         94     # Please see :ref:`astropy-cosmology-fast-integrals` for discussion
         95     # about what is being done here.
         96     if self._Tcmb0.value == 0:
    
    File ~/opt/anaconda3/envs/Astropy_Playground/lib/python3.10/site-packages/astropy/cosmology/flrw/base.py:144, in FLRW.__init__(self, H0, Om0, Ode0, Tcmb0, Neff, m_nu, Ob0, name, meta)
        142 self.Tcmb0 = Tcmb0
        143 self.Neff = Neff
    --> 144 self.m_nu = m_nu  # (reset later, this is just for unit validation)
        145 self.Ob0 = Ob0  # (must be after Om0)
        147 # Derived quantities:
        148 # Dark matter density; matter - baryons, if latter is not None.
    
    File ~/opt/anaconda3/envs/Astropy_Playground/lib/python3.10/site-packages/astropy/cosmology/parameter.py:128, in Parameter.__set__(self, cosmology, value)
        125     raise AttributeError(f"can't set attribute {self._attr_name} again")
        127 # Validate value, generally setting units if present
    --> 128 value = self.validate(cosmology, copy.deepcopy(value))
        130 # Make the value read-only, if ndarray-like
        131 if hasattr(value, "setflags"):
    
    File ~/opt/anaconda3/envs/Astropy_Playground/lib/python3.10/site-packages/astropy/cosmology/parameter.py:176, in Parameter.validate(self, cosmology, value)
        161 def validate(self, cosmology, value):
        162     """Run the validator on this Parameter.
        163 
        164     Parameters
       (...)
        174         (yes, that parameter order).
        175     """
    --> 176     return self.fvalidate(cosmology, self, value)
    
    File ~/opt/anaconda3/envs/Astropy_Playground/lib/python3.10/site-packages/astropy/cosmology/flrw/base.py:251, in FLRW.m_nu(self, param, value)
        248     return None  # None, regardless of input
        250 # Validate / set units
    --> 251 value = _validate_with_unit(self, param, value)
        253 # Check values and data shapes
        254 if value.shape not in ((), (nneutrinos,)):
    
    File ~/opt/anaconda3/envs/Astropy_Playground/lib/python3.10/site-packages/astropy/cosmology/parameter.py:334, in _validate_with_unit(cosmology, param, value)
        332 if param.unit is not None:
        333     with u.add_enabled_equivalencies(param.equivalencies):
    --> 334         value = u.Quantity(value, param.unit)
        335 return value
    
    File ~/opt/anaconda3/envs/Astropy_Playground/lib/python3.10/site-packages/astropy/units/quantity.py:457, in Quantity.__new__(cls, value, unit, dtype, copy, order, subok, ndmin)
        455 unit_string = v.string[v.end():].strip()
        456 if unit_string:
    --> 457     value_unit = Unit(unit_string)
        458     if unit is None:
        459         unit = value_unit  # signal no conversion needed below.
    
    File ~/opt/anaconda3/envs/Astropy_Playground/lib/python3.10/site-packages/astropy/units/core.py:2040, in _UnitMetaClass.__call__(self, s, represents, format, namespace, doc, parse_strict)
       2031 msg = ("'{}' did not parse as {}unit: {} "
       2032        "If this is meant to be a custom unit, "
       2033        "define it with 'u.def_unit'. To have it "
       (...)
       2037        "https://docs.astropy.org/en/latest/units/combining_and_defining.html"
       2038        .format(s, format_clause, str(e)))
       2039 if parse_strict == 'raise':
    -> 2040     raise ValueError(msg)
       2041 elif parse_strict == 'warn':
       2042     warnings.warn(msg, UnitsWarning)
    
    ValueError: '.. 0.06' did not parse as unit: Syntax error parsing unit '.. 0.06' If this is meant to be a custom unit, define it with 'u.def_unit'. To have it recognized inside a file reader or other code, enable it with 'u.add_enabled_units'. For details, see https://docs.astropy.org/en/latest/units/combining_and_defining.html
    
  8. nstarman commented on May 19, 2023

    @nstarman
    MemberAuthor

    I figured out the issue. It turns out Astropy's LaTeX reader doesn't work correctly...
    The units don't round-trip, causing the whole column to be read as a string.
    We'll have to get that fixed first!

    Screenshot 2023-05-19 at 18 10 14
  9. Mubin17 commented on May 22, 2023

    @Mubin17
    Contributor

    @nstarman Could you please guide me on how to fix this problem? Will I have to make changes in the read() method here

    def read(self, table):

    or in latex class over here
    class Latex(core.BaseReader):

  10. nstarman commented on May 23, 2023

    @nstarman
    MemberAuthor

    Oh, don't tackle that in the PR! way beyond scope 😆. I've opened #14853 to try to address this issue. I've asked @taldcroft for his opinion on how to fix this.

  11. Mubin17 commented on May 25, 2023

    @Mubin17
    Contributor

    Sounds good I will wait for the issue to get fixed.

  12. nstarman commented on May 25, 2023

    @nstarman
    MemberAuthor

    @Mubin17 If you're interested in contributing a read & write method, the AAS MRT (https://docs.astropy.org/en/stable/io/unified.html#built-in-table-readers-writers) one would be a good one. That already has unit support when reading, so its should be very similar to the LaTeX PR you just did.

  13. 3 remaining items

  14. removed this from the v6.0 milestone on Oct 4, 2023
  15. abdelrahman-hosam commented on Mar 21, 2025

    @abdelrahman-hosam

    I have a code that can turn a latex file into a txt (almost done) and I can add a word extra feature to be able to handle images and text formatting is that what you want or the desired output?

  16. nstarman commented on Mar 25, 2025

    @nstarman
    MemberAuthor

    I think this Issue is more focused on getting the Cosmology writer/reader to work with Astropy Table I/O to write / read in a latex table. It was decided in #14853 that reading in units is too challenging, but the broader issue of writing to a latex and reading from that latex are still available, if you are interesting in contributing!

  17. anishgkr21 commented on Jun 8, 2025

    @anishgkr21

    I’d like to take this “good first issue” and add a LaTeX reader/writer for astropy.cosmology. My plan is to create read_latex and write_latex functions in a new latex.py module (with accompanying tests) and expose them in init.py. I’ve already sketched out the code locally and will open a draft PR soon. Let me know if that sounds good, or if there’s any additional guidance before I begin! Thanks.

  18. kartavayv commented on Dec 31, 2025

    @kartavayv
    Contributor

    @nstarman Hi, Nathaniel I recently tried to contribute to this issue. Can you please take a look at code and tell me if some improvement needs to be done...?

  19. Pittu-Sharma commented on Feb 13, 2026

    @Pittu-Sharma

    Hello, I would like to contribute to this issue. Would it be possible to assign it to me?

  20. nstarman commented on Mar 1, 2026

    @nstarman
    MemberAuthor

    @Pittu-Sharma thanks for your interest in this issue. Someone is already working on this issue. If youre still interested I can suggest other Issues!

  21. molly22-byte commented on Mar 16, 2026

    @molly22-byte

    Hello, I would like to contribute to this issue. Would it be possible to assign it to me? OR can you please suggest me other issues to work upon?

  22. Naveen447-a11y commented on Mar 17, 2026

    @Naveen447-a11y

    hey ,can i work on this issue

  23. vnzhere commented on Mar 19, 2026

    @vnzhere

    Is this issue still relevant? I would like to work on it if it is still open.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions