manoharan-lab / holopy

Hologram processing and light scattering in python
GNU General Public License v3.0
131 stars 50 forks source link

Unable to save models with transformed priors #388

Closed levbershadsky closed 3 years ago

levbershadsky commented 3 years ago

Holopy cannot save priors that are transformed using numpy ufuncs. This can be reproduced with this model:

n1 = np.array(prior.Uniform(1.55, 2.05))
n2 = np.array(prior.Uniform(1.55, 2.05))
testSphere = Sphere(n=n1+n2/n1, r=1, center=[0,0,0])

hp.save("test.h5", testSphere)

This can be traced back to the ufunc through yaml.dump(testSphere.n.transformation).

barkls commented 3 years ago

Thanks for posting this! I'm not sure this is the same error you were seeing before though... The error points back to trying to iterate over Uniform, which isn't an iterable, but I think previously you had someting about strings and names?

levbershadsky commented 3 years ago

On my machine the error for that code block is:

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-3-552730b5ce52> in <module>
----> 1 hp.save("test.h5", testSphere)

~/anaconda3/envs/holo/lib/python3.8/site-packages/holopy/core/io/io.py in save(outf, obj)
    320         ds.to_netcdf(default_extension(outf), engine='h5netcdf')
    321     else:
--> 322         serialize.save(outf, obj)
    323 
    324 

~/anaconda3/envs/holo/lib/python3.8/site-packages/holopy/core/io/serialize.py in save(outf, obj)
     42         close = True
     43 
---> 44     outf.write(yaml.dump(obj, default_flow_style=True).encode())
     45     if close:
     46         outf.close()

~/anaconda3/envs/holo/lib/python3.8/site-packages/yaml/__init__.py in dump(data, stream, Dumper, **kwds)
    288     If stream is None, return the produced string instead.
    289     """
--> 290     return dump_all([data], stream, Dumper=Dumper, **kwds)
    291 
    292 def safe_dump_all(documents, stream=None, **kwds):

~/anaconda3/envs/holo/lib/python3.8/site-packages/yaml/__init__.py in dump_all(documents, stream, Dumper, default_style, default_flow_style, canonical, indent, width, allow_unicode, line_break, encoding, explicit_start, explicit_end, version, tags, sort_keys)
    276         dumper.open()
    277         for data in documents:
--> 278             dumper.represent(data)
    279         dumper.close()
    280     finally:

~/anaconda3/envs/holo/lib/python3.8/site-packages/yaml/representer.py in represent(self, data)
     25 
     26     def represent(self, data):
---> 27         node = self.represent_data(data)
     28         self.serialize(node)
     29         self.represented_objects = {}

~/anaconda3/envs/holo/lib/python3.8/site-packages/yaml/representer.py in represent_data(self, data)
     46         data_types = type(data).__mro__
     47         if data_types[0] in self.yaml_representers:
---> 48             node = self.yaml_representers[data_types[0]](self, data)
     49         else:
     50             for data_type in data_types:

~/anaconda3/envs/holo/lib/python3.8/site-packages/holopy/core/holopy_object.py in to_yaml(cls, dumper, data)
     87         for key, item in data._iteritems():
     88             node_key = dumper.represent_data(key)
---> 89             node_value = dumper.represent_data(item)
     90             value.append((node_key, node_value))
     91         return node

~/anaconda3/envs/holo/lib/python3.8/site-packages/yaml/representer.py in represent_data(self, data)
     46         data_types = type(data).__mro__
     47         if data_types[0] in self.yaml_representers:
---> 48             node = self.yaml_representers[data_types[0]](self, data)
     49         else:
     50             for data_type in data_types:

~/anaconda3/envs/holo/lib/python3.8/site-packages/holopy/core/holopy_object.py in to_yaml(cls, dumper, data)
     87         for key, item in data._iteritems():
     88             node_key = dumper.represent_data(key)
---> 89             node_value = dumper.represent_data(item)
     90             value.append((node_key, node_value))
     91         return node

~/anaconda3/envs/holo/lib/python3.8/site-packages/yaml/representer.py in represent_data(self, data)
     50             for data_type in data_types:
     51                 if data_type in self.yaml_multi_representers:
---> 52                     node = self.yaml_multi_representers[data_type](self, data)
     53                     break
     54             else:

~/anaconda3/envs/holo/lib/python3.8/site-packages/yaml/representer.py in represent_object(self, data)
    329         if dictitems is not None:
    330             dictitems = dict(dictitems)
--> 331         if function.__name__ == '__newobj__':
    332             function = args[0]
    333             args = args[1:]

AttributeError: 'str' object has no attribute '__name__'
barkls commented 3 years ago

Hmm I'm not getting that error. Can you check your yaml and pyyaml versions?

levbershadsky commented 3 years ago
# Name                    Version                   Build  Channel
pyyaml                    5.4.1            py38h497a2fe_0    conda-forge
yaml                      0.2.5                h516909a_0    conda-forge
barkls commented 3 years ago

Can you also check your numpy version?

levbershadsky commented 3 years ago
# Name                    Version                   Build  Channel
numpy                     1.20.1           py38h18fd61f_0    conda-forge
barkls commented 3 years ago

Downgrading to numpy 1.19 should let you save your objects correctly.

barkls commented 3 years ago

The develop branch should have an alternate fix that works for numpy 1.20 as well as earlier versions. @levbershadsky Please reopen this issue if the problem persists.