teamtomo / starfile

STAR file I/O in Python
https://teamtomo.org/starfile/
BSD 3-Clause "New" or "Revised" License
44 stars 19 forks source link

Starfile write fails #61

Closed lglass closed 5 months ago

lglass commented 5 months ago

Description

I'm trying to write a simple star file. It writes the data header but fails to write the data frame with the error

AttributeError: 'DataFrame' object has no attribute 'map'

What I Did

import pandas as pd
import starfile

star = pd.DataFrame()
star["rlnCoordinateX"] = 0.0
star["rlnCoordinateY"] = 0.0
star["rlnAutopickFigureOfMerit"] = 10.
star["rlnClassNumber"] = 0
star["rlnAnglePsi"] = 0.0

starfile.write(data=star, filename="test.star", quote_all_strings=False)
Output:
{
    "name": "AttributeError",
    "message": "'DataFrame' object has no attribute 'map'",
    "stack": "---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Input In [24], in <cell line: 2>()

File ~/miniforge3/envs/ml/lib/python3.9/site-packages/starfile/functions.py:76, in write(data, filename, float_format, sep, na_rep, quote_character, quote_all_strings, **kwargs)
     50 def write(
     51     data: Union[DataBlock, Dict[str, DataBlock], List[DataBlock]],
     52     filename: PathLike,
   (...)
     58     **kwargs
     59 ):
     60     \"\"\"Write data to disk in the STAR format.
     61 
     62     Parameters
   (...)
     74         Representation of null values, will be passed to pandas.
     75     \"\"\"
---> 76     StarWriter(
     77         data,
     78         filename=filename,
     79         float_format=float_format,
     80         na_rep=na_rep,
     81         separator=sep,
     82         quote_character=quote_character,
     83         quote_all_strings=quote_all_strings,
     84     )

File ~/miniforge3/envs/ml/lib/python3.9/site-packages/starfile/writer.py:43, in StarWriter.__init__(self, data_blocks, filename, float_format, separator, na_rep, quote_character, quote_all_strings)
     41 self.buffer = TextBuffer()
     42 self.backup_if_file_exists()
---> 43 self.write()

File ~/miniforge3/envs/ml/lib/python3.9/site-packages/starfile/writer.py:67, in StarWriter.write(self)
     65 write_package_info(self.filename)
     66 write_blank_lines(self.filename, n=2)
---> 67 self.write_data_blocks()

File ~/miniforge3/envs/ml/lib/python3.9/site-packages/starfile/writer.py:80, in StarWriter.write_data_blocks(self)
     72     write_simple_block(
     73         file=self.filename,
     74         block_name=block_name,
   (...)
     77         quote_all_strings=self.quote_all_strings
     78     )
     79 elif isinstance(block, pd.DataFrame):
---> 80     write_loop_block(
     81         file=self.filename,
     82         block_name=block_name,
     83         df=block,
     84         float_format=self.float_format,
     85         separator=self.sep,
     86         na_rep=self.na_rep,
     87         quote_character=self.quote_character,
     88         quote_all_strings=self.quote_all_strings
     89     )

File ~/miniforge3/envs/ml/lib/python3.9/site-packages/starfile/writer.py:183, in write_loop_block(file, block_name, df, float_format, separator, na_rep, quote_character, quote_all_strings)
    180     f.write('\
'.join(header_lines))
    181     f.write('\
')
--> 183 df = df.map(lambda x: f'{quote_character}{x}{quote_character}' 
    184             if isinstance(x, str) and (quote_all_strings or \" \" in x or x == \"\") 
    185             else x)
    187 # write data
    188 df.to_csv(
    189     path_or_buf=file,
    190     mode='a',
   (...)
    196     quoting=csv.QUOTE_NONE
    197 )

File ~/miniforge3/envs/ml/lib/python3.9/site-packages/pandas/core/generic.py:5989, in NDFrame.__getattr__(self, name)
   5982 if (
   5983     name not in self._internal_names_set
   5984     and name not in self._metadata
   5985     and name not in self._accessors
   5986     and self._info_axis._can_hold_identifiers_and_holds_name(name)
   5987 ):
   5988     return self[name]
-> 5989 return object.__getattribute__(self, name)

AttributeError: 'DataFrame' object has no attribute 'map'"
}
alisterburt commented 5 months ago

There was a pandas deprecation and pandas.map is only available in pandas>=2.1.0

https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.map.html

I'm not sure how you ended up with a broken environment but if you do pip install --upgrade pandas you should be golden! I'll check our requirements are properly specified here

lglass commented 5 months ago

Thanks!

alisterburt commented 5 months ago

https://github.com/teamtomo/starfile/blob/main/pyproject.toml#L40 looks like requirements are properly specified

Sorry you ended up with a broken env, if I don't hear back from you I'll close here assuming it's fixed by the pandas upgrade 🙂