echemdb / unitpackage

A Python library to interact with a collection of frictionless datapackages
https://echemdb.github.io/unitpackage/
GNU General Public License v3.0
4 stars 3 forks source link

Rescaling rescaled entry to 'original' values #12

Closed DunklesArchipel closed 1 year ago

DunklesArchipel commented 1 year ago

Recsaling an en entry to other units and then trying to transform the entry to its original values fails.

The problem appeared upon creating the documentation in echemdb/echemdb#51

from echemdb.cv.cv_database import CVDatabase
db = CVDatabase()
entry = db['engstfeld_2018_polycrystalline_17743_f4b_1']
rescaled_entry = entry.rescale({'t' : 'h', 'E': 'mV', 'j' : 'uA / cm2'})
rescaled_entry.df.head()
original_entry = rescaled_entry.rescale('original') # this fails
original_entry.df.head()
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[21], line 1
----> 1 original_entry = rescaled_entry.rescale('original')
      2 original_entry.df.head()

File x:\github\echemdb\echemdb\cv\cv_entry.py:106, in CVEntry.rescale(self, units)
     87 r"""
     88 Return a rescaled :class:`CVEntry` with axes in the specified ``units``.
     89 
   (...)
    102 
    103 """
    104 if units == "original":
    105     units = {
--> 106         field["name"]: field["unit"] for field in self.figure_description.fields
    107     }
    109 return super().rescale(units)

File x:\github\echemdb\echemdb\entry.py:126, in Entry.__getattr__(self, name)
    108 def __getattr__(self, name):
    109     r"""
    110     Return a property of the data package's descriptor.
    111 
   (...)
    124 
    125     """
--> 126     return getattr(self._descriptor, name)

File x:\github\echemdb\echemdb\entry.py:145, in Entry._descriptor(self)
    143 @property
    144 def _descriptor(self):
--> 145     return Descriptor(self.package.to_dict())

File C:\Miniconda3\envs\echemdb\lib\site-packages\frictionless\metadata.py:212, in Metadata.to_dict(self)
    210 def to_dict(self) -> IDescriptor:
    211     """Export metadata as dictionary (alias for "to_descriptor")"""
--> 212     return self.to_descriptor()

File C:\Miniconda3\envs\echemdb\lib\site-packages\frictionless\metadata.py:189, in Metadata.to_descriptor(self, validate)
    188 def to_descriptor(self, *, validate: bool = False) -> IDescriptor:
--> 189     descriptor = self.metadata_export()
    190     if validate:
    191         Error = self.metadata_Error or platform.frictionless_errors.MetadataError

File C:\Miniconda3\envs\echemdb\lib\site-packages\frictionless\package\package.py:744, in Package.metadata_export(self)
    743 def metadata_export(self):
--> 744     descriptor = super().metadata_export()
    746     # Frictionless
    747     if system.standards == "v2":

File C:\Miniconda3\envs\echemdb\lib\site-packages\frictionless\metadata.py:421, in Metadata.metadata_export(self, exclude)
    419 if Class:
    420     if isinstance(value, list):
--> 421         value = [item.to_descriptor_source() for item in value]  # type: ignore
    422     else:
    423         value = value.to_descriptor_source()  # type: ignore

File C:\Miniconda3\envs\echemdb\lib\site-packages\frictionless\metadata.py:421, in <listcomp>(.0)
    419 if Class:
    420     if isinstance(value, list):
--> 421         value = [item.to_descriptor_source() for item in value]  # type: ignore
    422     else:
    423         value = value.to_descriptor_source()  # type: ignore

File C:\Miniconda3\envs\echemdb\lib\site-packages\frictionless\metadata.py:200, in Metadata.to_descriptor_source(self)
    198 def to_descriptor_source(self) -> Union[IDescriptor, str]:
    199     """Export metadata as a descriptor or a descriptor path"""
--> 200     descriptor = self.to_descriptor()
    201     if self.metadata_descriptor_path:
    202         if self.metadata_descriptor_initial == descriptor:

File C:\Miniconda3\envs\echemdb\lib\site-packages\frictionless\metadata.py:189, in Metadata.to_descriptor(self, validate)
    188 def to_descriptor(self, *, validate: bool = False) -> IDescriptor:
--> 189     descriptor = self.metadata_export()
    190     if validate:
    191         Error = self.metadata_Error or platform.frictionless_errors.MetadataError

File C:\Miniconda3\envs\echemdb\lib\site-packages\frictionless\resource\resource.py:897, in Resource.metadata_export(self)
    896 def metadata_export(self):
--> 897     descriptor = super().metadata_export()
    899     # Data
    900     data = descriptor.get("data")

File C:\Miniconda3\envs\echemdb\lib\site-packages\frictionless\metadata.py:413, in Metadata.metadata_export(self, exclude)
    411 if name in exclude:
    412     continue
--> 413 if name != "type" and not self.has_defined(stringcase.snakecase(name)):
    414     continue
    415 value = getattr(self, stringcase.snakecase(name), None)

File C:\Miniconda3\envs\echemdb\lib\site-packages\frictionless\metadata.py:125, in Metadata.has_defined(self, name)
    124 def has_defined(self, name: str) -> bool:
--> 125     return name in self.list_defined()

File C:\Miniconda3\envs\echemdb\lib\site-packages\frictionless\metadata.py:117, in Metadata.list_defined(self)
    115     if isinstance(value, type):
    116         value = value.__dict__.copy()  # type: ignore
--> 117     if value != default:
    118         defined.append(name)
    119 return defined

File C:\Miniconda3\envs\echemdb\lib\site-packages\pandas\core\ops\common.py:72, in _unpack_zerodim_and_defer.<locals>.new_method(self, other)
     68             return NotImplemented
     70 other = item_from_zerodim(other)
---> 72 return method(self, other)

File C:\Miniconda3\envs\echemdb\lib\site-packages\pandas\core\arraylike.py:46, in OpsMixin.__ne__(self, other)
     44 @unpack_zerodim_and_defer("__ne__")
     45 def __ne__(self, other):
---> 46     return self._cmp_method(other, operator.ne)

File C:\Miniconda3\envs\echemdb\lib\site-packages\pandas\core\frame.py:7579, in DataFrame._cmp_method(self, other, op)
   7576 def _cmp_method(self, other, op):
   7577     axis = 1  # only relevant for Series other case
-> 7579     self, other = ops.align_method_FRAME(self, other, axis, flex=False, level=None)
   7581     # See GH#4537 for discussion of scalar op behavior
   7582     new_data = self._dispatch_frame_op(other, op, axis=axis)

File C:\Miniconda3\envs\echemdb\lib\site-packages\pandas\core\ops\__init__.py:282, in align_method_FRAME(left, right, axis, flex, level)
    278         raise ValueError(
    279             f"Unable to coerce list of {type(right[0])} to Series/DataFrame"
    280         )
    281     # GH17901
--> 282     right = to_series(right)
    284 if flex is not None and isinstance(right, ABCDataFrame):
    285     if not left._indexed_same(right):

File C:\Miniconda3\envs\echemdb\lib\site-packages\pandas\core\ops\__init__.py:239, in align_method_FRAME.<locals>.to_series(right)
    237 else:
    238     if len(left.columns) != len(right):
--> 239         raise ValueError(
    240             msg.format(req_len=len(left.columns), given_len=len(right))
    241         )
    242     right = left._constructor_sliced(right, index=left.columns)
    243 return right

ValueError: Unable to coerce to Series, length must be 3: given 0