-
Notifications
You must be signed in to change notification settings - Fork 35
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
serialization of basemesh #182
Conversation
… the x0 property in the tree mesh so that x0 is stored at the python layer and a validator calls _set_x0 which lives at the cpp layer to clear the grids and update cell locaitons
…as well as instantiation from the serialized dictionary.
Codecov Report
@@ Coverage Diff @@
## master #182 +/- ##
==========================================
- Coverage 82.1% 82.09% -0.02%
==========================================
Files 23 23
Lines 4974 4982 +8
==========================================
+ Hits 4084 4090 +6
- Misses 890 892 +2
Continue to review full report at Codecov.
|
Codecov Report
@@ Coverage Diff @@
## master #182 +/- ##
==========================================
+ Coverage 82.1% 82.17% +0.06%
==========================================
Files 23 23
Lines 4974 4993 +19
==========================================
+ Hits 4084 4103 +19
Misses 890 890
Continue to review full report at Codecov.
|
Got it sorted @jcapriot: It was a subtle error with the behaviour of |
…y array using isinstance rather than type
👋 @jcapriot: whenever you have a chance, would you mind taking another look and if you think it is good to go then approve the pr? or if there are still changes you see fit, please let me know. Thanks! |
@lheagy It looks good to me. Can you look at the TreeMesh serialize/deserialize too? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good to me! Serialization of all the meshes!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be great to have save
/read
convenience methods so that users could easily call .save()
on any mesh to serialize it to a file.
Also, it would be great to have a convenience method to load any serialized discretize
mesh so that you don't have to know what kind of mesh is serialized. For example:
import discretize
mesh = discretize.read('my_serialized_mesh.msh')
That way a user doesn't have to call a class-specific deserialize method in addition to reading it from the file.
mesh = discretize.TreeMesh.deserialize(read_from_file)
Or is this type of functionality already implemented? It's not clear to me.
In summary, I think there should be a simple way to save/load any mesh so that a user doesn't have to remember if they used a TensorMesh or a TreeMesh, etc.
@@ -632,8 +649,17 @@ def plotSlice( | |||
plt.show() | |||
return tuple(out) | |||
|
|||
def save(self, *args, **kwargs): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could this method stay and allow a user to pass a file name which will serialize any mesh to a file? For example:
mesh = some_discretize_mesh_of_any_type
mesh.save('my_awesome_mesh.msh')
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was removed because It was originally overriding it here to explicitly say that save wouldn't work on the TreeMesh, now it behaves like the other meshes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The msh
and mesh
extensions are greatly overused across viz libraries and other mesh analysis software. I think it would be best to step away from the msh
/mesh
convention I've seen used with discretize and towards something more distinct.
I think this PR would be a great place to standardize how meshes are saved - perhaps have the default extension to this save
method be something like: .dmesh
, .discretize
, .simpeg
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was removed because It was originally overriding it here to explicitly say that save wouldn't work on the TreeMesh, now it behaves like the other meshes
Ah whoops - I wasn't looking closely enough - I see now that save
is indeed implemented here for all meshes
discretize/discretize/base/base_mesh.py
Line 395 in 7c0af69
def save(self, filename='mesh.json', verbose=False): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My note about the file extension remains - instead of .json
, would something more distinct be appropriate?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @banesullivan: yes, the save / load should be working for all mesh-types at this point in discretize.
I am inclined to leave the file extension as json
as we can then take advantage of viewers and and tools for json
. For example, in JupyterLab, there is a json
viewer that nests properties nicely and such, but this by default will only work if the file extension is json
(e.g. I renamed the one on the right to .model
).
Do you have a use-case in mind for why we would need it to be something more distinct?
I will merge this in as |
return True | ||
elif isinstance(f, np.ndarray) and f.size == 1 and type(f[0]) in scalarTypes: | ||
elif isinstance(f, np.ndarray) and f.size == 1 and isinstance(f[0], scalarTypes): | ||
return True | ||
return False | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for commenting on an old PR @lheagy. I just stumbled upon that and I was wondering if there is any benefit of discretize.utils.codeutils.isScalar(f)
(lines 6-15) over simply np.size(f) == 1
? Just thought because you extended it for complex number, so it is fragile on the defined scalarTypes
and will fail for all others (e.g., int8
, float32
, complex64
, etc).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No worries @prisae, thanks for raising this. In the scalarTypes
we do have np.number
which np.int8
and others inherit.
I think that just checking size isn't quite enough. For example, a 2D 1-element array currently returns False
from isScalar as the first entry is an array. I think that that logic is what we want.
For example in the TensorType
code, we should never be working with 2D arrays.
https://github.com/simpeg/discretize/blob/master/discretize/utils/matutils.py#L299-L309
However, this might take a bit more thought. Maybe we do want anything that has one element to evaluate True
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it might be good to think about it and agree on that, and then write a little docstring with it. Because the behaviour of isScalar
is not quite obvious from just looking at it.
Here some values
np.isscalar(x) | np.ndim(x) | np.size(x)==1 | isScalar(x) | |
---|---|---|---|---|
0 | True | 0 | True | True |
np.array(0) | False | 0 | True | IndexError |
np.atleast_1d(0) | False | 1 | True | True |
np.atleast_2d(0) | False | 2 | True | False |
np.atleast_3d(0) | False | 3 | True | False |
isScalar
currently fails for a 0D numpy array. However, instead of fixing isScalar
for that case we might consider its purpose first.
What is the use-case that a one-element 1D array passes as scalar, but a one-element 2D or 3D array not?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here the failure for the 0D numpy array:
In [58]: isScalar(np.array(0))
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-58-525f9e80cd80> in <module>
----> 1 isScalar(np.array(0))
~/anaconda3/lib/python3.7/site-packages/discretize/utils/codeutils.py in isScalar(f)
11 if isinstance(f, scalarTypes):
12 return True
---> 13 elif isinstance(f, np.ndarray) and f.size == 1 and isinstance(f[0], scalarTypes):
14 return True
15 return False
IndexError: too many indices for array
update instantiation of basemesh so meshes can be formed from their serialized state, e.g.
will have the value of
_n
stored, thus,n
does not need to be provided on instantiation