From 9e190454689b3961df7ef6b5cb290a435a070e9e Mon Sep 17 00:00:00 2001 From: Qianqian Fang Date: Sun, 19 Feb 2023 12:35:25 -0500 Subject: [PATCH 1/5] reading and writing JSON nased based mesh files (.jmsh, .bmsh) --- nibabel/__init__.py | 1 + nibabel/imageclasses.py | 2 + nibabel/jmesh/__init__.py | 19 ++++ nibabel/jmesh/jmesh.py | 226 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 248 insertions(+) create mode 100644 nibabel/jmesh/__init__.py create mode 100644 nibabel/jmesh/jmesh.py diff --git a/nibabel/__init__.py b/nibabel/__init__.py index 50dca14515..ac7f39ae7c 100644 --- a/nibabel/__init__.py +++ b/nibabel/__init__.py @@ -70,6 +70,7 @@ ) from .spm2analyze import Spm2AnalyzeHeader, Spm2AnalyzeImage from .spm99analyze import Spm99AnalyzeHeader, Spm99AnalyzeImage +from .jmesh import JMesh # isort: split diff --git a/nibabel/imageclasses.py b/nibabel/imageclasses.py index e2dbed129d..bc135f9a9f 100644 --- a/nibabel/imageclasses.py +++ b/nibabel/imageclasses.py @@ -19,6 +19,7 @@ from .parrec import PARRECImage from .spm2analyze import Spm2AnalyzeImage from .spm99analyze import Spm99AnalyzeImage +from .jmesh import JMesh # Ordered by the load/save priority. all_image_classes = [ @@ -36,6 +37,7 @@ PARRECImage, GiftiImage, AFNIImage, + JMesh, ] # Image classes known to require spatial axes to be first in index ordering. diff --git a/nibabel/jmesh/__init__.py b/nibabel/jmesh/__init__.py new file mode 100644 index 0000000000..f555d6a70a --- /dev/null +++ b/nibabel/jmesh/__init__.py @@ -0,0 +1,19 @@ +# emacs: -*- mode: python-mode; py-indent-offset: 4; indent-tabs-mode: nil -*- +# vi: set ft=python sts=4 ts=4 sw=4 et: +### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ## +# +# See COPYING file distributed along with the NiBabel package for the +# copyright and license terms. +# +### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ## +"""JSON and BJData based JMesh format IO + +.. currentmodule:: nibabel.jmesh + +.. autosummary:: + :toctree: ../generated + + jmesh +""" + +from .jmesh import load, save, JMesh, default_header diff --git a/nibabel/jmesh/jmesh.py b/nibabel/jmesh/jmesh.py new file mode 100644 index 0000000000..c3a9e85add --- /dev/null +++ b/nibabel/jmesh/jmesh.py @@ -0,0 +1,226 @@ +# emacs: -*- mode: python-mode; py-indent-offset: 4; indent-tabs-mode: nil -*- +# vi: set ft=python sts=4 ts=4 sw=4 et: +### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ## +# +# See COPYING file distributed along with the NiBabel package for the +# copyright and license terms. +# +### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ## +# General JMesh Input - Output to and from the filesystem +# Qianqian Fang +############## + +__all__ = ['JMesh','read','write','default_header'] + +from jdata import (load as jdload, save as jdsave) +import numpy as np +from ..filebasedimages import FileBasedImage + +default_header = { + "JMeshVersion":"0.5", + "Comment":"Created by NiPy with NeuroJSON JMesh specification", + "AnnotationFormat":"https://neurojson.org/jmesh/draft2", + "Parser":{ + "Python":[ + "https://pypi.org/project/jdata", + "https://pypi.org/project/bjdata" + ], + "MATLAB":[ + "https://github.com/NeuroJSON/jnifty", + "https://github.com/NeuroJSON/jsonlab" + ], + "JavaScript":"https://github.com/NeuroJSON/jsdata", + "CPP":"https://github.com/NeuroJSON/json", + "C":"https://github.com/NeuroJSON/ubj" + } +} + +class JMesh(FileBasedImage): + """JMesh: a simple data structure representing a brain surface + + * Description - JMesh defines a set of language-neutral JSON annotations for + storage and exchange of mesh-related data. The details of the specification + can be found in NeuroJSON's website at https://neurojson.org + + * Child Elements: [NA] + * Text Content: [NA] + + Attributes + ---------- + info: a dict + A dict object storing the metadata (`_DataInfo_`) section of the JMesh + file + node : 2-D list or numpy array + A 2-D numpy.ndarray object to store the vertices of the mesh + nodelabel : 1-D list or numpy array + A 1-D numpy.ndarray object to store the label of each vertex + face : 2-D list or numpy array + A 2-D numpy.ndarray object to store the triangular elements of the + mesh; indices start from 1 + facelabel : 1-D list or numpy array + A 1-D numpy.ndarray object to store the label of each triangle + raw : a dict + The raw data loaded from the .jmsh or .bmsh file + """ + valid_exts = ('.jmsh', '.bmsh') + files_types = (('image', '.jmsh'), ('image', '.bmsh')) + makeable = False + rw = True + + def __init__(self, info=None, node=None, nodelabel=None, face=None, + facelabel=None): + + self.raw = {} + if(not info is None): + self.raw['_DataInfo_'] = info + + if(not nodelabel is None): + self.raw['MeshVertex3'] = {'Data': node, 'Properties': {'Tag': nodelabel} } + self.node = self.raw['MeshVertex3']['Data'] + self.nodelabel = self.raw['MeshVertex3']['Properties']['Tag'] + else: + self.raw['MeshVertex3'] = node + self.node = self.raw['MeshVertex3'] + + if(not facelabel is None): + self.raw['MeshTri3'] = {'Data': face, 'Properties': {'Tag': facelabel} } + self.face = self.raw['MeshTri3']['Data'] + self.facelabel = self.raw['MeshTri3']['Properties']['Tag'] + else: + self.raw['MeshTri3'] = face + self.face = self.raw['MeshTri3'] + + @classmethod + def from_filename(self, filename, opt={}, **kwargs): + self = read(filename, opt, **kwargs) + return self + + @classmethod + def to_filename(self, filename, opt={}, **kwargs): + write(self, filename, opt, **kwargs) + +def read(filename, opt={}, **kwargs): + """ Load a JSON or binary JData (BJData) based JMesh file + + Parameters + ---------- + filename : string + The JMesh file to open, it has usually ending .gii + opt: a dict that may contain below option keys + ndarray: boolean, if True, node/face/nodelabel/facelabel are converted + to numpy.ndarray, otherwise, leave those unchanged + kwargs: additional keyword arguments for `json.load` when .jmsh file is being loaded + + Returns + ------- + mesh : a JMesh object + Return a JMesh object containing mesh data fields such as node, face, nodelabel etc + """ + opt.setdefault('ndarray',True) + + mesh = JMesh + mesh.raw = jdload(filename, opt, **kwargs) + + #-------------------------------------------------- + # read metadata as `info` + #-------------------------------------------------- + if('_DataInfo_' in mesh.raw): + mesh.info = mesh.raw['_DataInfo_'] + + #-------------------------------------------------- + # read vertices as `node` and `nodelabel` + #-------------------------------------------------- + if('MeshVertex3' in mesh.raw): + mesh.node = mesh.raw['MeshVertex3'] + elif('MeshNode' in mesh.raw): + mesh.node = mesh.raw['MeshNode'] + else: + raise Exception('JMesh', 'JMesh surface must contain node (MeshVertex3 or MeshNode)') + + if(isinstance(mesh.node, dict)): + if(('Properties' in mesh.node) and ('Tag' in mesh.node['Properties'])): + mesh.nodelabel = mesh.node['Properties']['Tag'] + if('Data' in mesh.node): + mesh.node = mesh.node['Data'] + if(isinstance(mesh.node, np.ndarray) and mesh.node.ndim == 2 and mesh.node.shape[1] > 3): + mesh.nodelabel = mesh.node[:,3:] + mesh.node = mesh.node[:, 0:3] + + #-------------------------------------------------- + # read triangles as `face` and `facelabel` + #-------------------------------------------------- + if('MeshTri3' in mesh.raw): + mesh.face = mesh.raw['MeshTri3'] + elif('MeshSurf' in mesh.raw): + mesh.face = mesh.raw['MeshSurf'] + + if(isinstance(mesh.face, dict)): + if(('Properties' in mesh.face) and ('Tag' in mesh.face['Properties'])): + mesh.facelabel = mesh.face['Properties']['Tag'] + if('Data' in mesh.face): + mesh.face = mesh.face['Data'] + if(isinstance(mesh.face, np.ndarray) and mesh.face.ndim == 2 and mesh.face.shape[1] > 3): + mesh.facelabel = mesh.face[:,3:] + mesh.face = mesh.face[:, 0:3] + + #-------------------------------------------------- + # convert to numpy ndarray + #-------------------------------------------------- + if(opt['ndarray']): + if hasattr(mesh, 'node') and (not mesh.node is None) and (not isinstance(mesh.node, np.ndarray)): + mesh.node = np.array(mesh.node) + + if hasattr(mesh, 'face') and (not mesh.face is None) and (not isinstance(mesh.face, np.ndarray)): + mesh.face = np.array(mesh.face) + + if hasattr(mesh, 'nodelabel') and (not mesh.nodelabel is None) and (not isinstance(mesh.nodelabel, np.ndarray)): + mesh.nodelabel = np.array(mesh.nodelabel) + + if hasattr(mesh, 'facelabel') and (not mesh.facelabel is None) and (not isinstance(mesh.facelabel, np.ndarray)): + mesh.facelabel = np.array(mesh.facelabel) + + return mesh + +def write(mesh, filename, opt={}, **kwargs): + """ Save the current mesh to a new file + + Parameters + ---------- + mesh : a JMesh object + filename : string + Filename to store the JMesh file (.jmsh for JSON based JMesh and + .bmsh for binary JMesh files) + opt: a dict that may contain below option keys + ndarray: boolean, if True, node/face/nodelabel/facelabel are converted + to numpy.ndarray, otherwise, leave those unchanged + kwargs: additional keyword arguments for `json.dump` when .jmsh file is being saved + + Returns + ------- + None + + We update the mesh related data fields `MeshVetex3`, `MeshTri3` and metadata `_DataInfo_` + from mesh.node, mesh.face and mesh.info, then save mesh.raw to JData files + """ + + if not hasattr(mesh, 'raw') or mesh.raw is None: + mesh.raw = {} + + if hasattr(mesh, 'info') and not mesh.info is None: + mesh.raw['_DataInfo_']=mesh.info + if hasattr(mesh, 'node') and not mesh.node is None: + if(hasattr(mesh, 'facelabel') and not mesh.nodelabel is None): + mesh.raw['MeshVertex3']={'Data': mesh.node, 'Properties': {'Tag': mesh.nodelabel}} + else: + mesh.raw['MeshVertex3']=mesh.node + + if hasattr(mesh, 'info') and not mesh.face is None: + if(hasattr(mesh, 'facelabel') and not mesh.facelabel is None): + mesh.raw['MeshTri3']={'Data': mesh.face, 'Properties': {'Tag': mesh.facelabel}} + else: + mesh.raw['MeshTri3']=mesh.face + + return jdsave(mesh.raw, filename, opt, **kwargs) + +load = read +save = write From 9de951c6c55a6f7855cf9b9cde7295a0c8e95e5a Mon Sep 17 00:00:00 2001 From: Qianqian Fang Date: Sun, 19 Feb 2023 12:41:40 -0500 Subject: [PATCH 2/5] run blue to format jmesh new units --- nibabel/jmesh/jmesh.py | 140 ++++++++++++++++++++++------------------- 1 file changed, 77 insertions(+), 63 deletions(-) diff --git a/nibabel/jmesh/jmesh.py b/nibabel/jmesh/jmesh.py index c3a9e85add..716d266e7c 100644 --- a/nibabel/jmesh/jmesh.py +++ b/nibabel/jmesh/jmesh.py @@ -10,31 +10,26 @@ # Qianqian Fang ############## -__all__ = ['JMesh','read','write','default_header'] +__all__ = ['JMesh', 'read', 'write', 'default_header'] -from jdata import (load as jdload, save as jdsave) +from jdata import load as jdload, save as jdsave import numpy as np from ..filebasedimages import FileBasedImage default_header = { - "JMeshVersion":"0.5", - "Comment":"Created by NiPy with NeuroJSON JMesh specification", - "AnnotationFormat":"https://neurojson.org/jmesh/draft2", - "Parser":{ - "Python":[ - "https://pypi.org/project/jdata", - "https://pypi.org/project/bjdata" - ], - "MATLAB":[ - "https://github.com/NeuroJSON/jnifty", - "https://github.com/NeuroJSON/jsonlab" - ], - "JavaScript":"https://github.com/NeuroJSON/jsdata", - "CPP":"https://github.com/NeuroJSON/json", - "C":"https://github.com/NeuroJSON/ubj" - } + 'JMeshVersion': '0.5', + 'Comment': 'Created by NiPy with NeuroJSON JMesh specification', + 'AnnotationFormat': 'https://neurojson.org/jmesh/draft2', + 'Parser': { + 'Python': ['https://pypi.org/project/jdata', 'https://pypi.org/project/bjdata'], + 'MATLAB': ['https://github.com/NeuroJSON/jnifty', 'https://github.com/NeuroJSON/jsonlab'], + 'JavaScript': 'https://github.com/NeuroJSON/jsdata', + 'CPP': 'https://github.com/NeuroJSON/json', + 'C': 'https://github.com/NeuroJSON/ubj', + }, } + class JMesh(FileBasedImage): """JMesh: a simple data structure representing a brain surface @@ -62,28 +57,28 @@ class JMesh(FileBasedImage): raw : a dict The raw data loaded from the .jmsh or .bmsh file """ + valid_exts = ('.jmsh', '.bmsh') files_types = (('image', '.jmsh'), ('image', '.bmsh')) makeable = False rw = True - def __init__(self, info=None, node=None, nodelabel=None, face=None, - facelabel=None): + def __init__(self, info=None, node=None, nodelabel=None, face=None, facelabel=None): self.raw = {} - if(not info is None): + if not info is None: self.raw['_DataInfo_'] = info - if(not nodelabel is None): - self.raw['MeshVertex3'] = {'Data': node, 'Properties': {'Tag': nodelabel} } + if not nodelabel is None: + self.raw['MeshVertex3'] = {'Data': node, 'Properties': {'Tag': nodelabel}} self.node = self.raw['MeshVertex3']['Data'] self.nodelabel = self.raw['MeshVertex3']['Properties']['Tag'] else: self.raw['MeshVertex3'] = node self.node = self.raw['MeshVertex3'] - if(not facelabel is None): - self.raw['MeshTri3'] = {'Data': face, 'Properties': {'Tag': facelabel} } + if not facelabel is None: + self.raw['MeshTri3'] = {'Data': face, 'Properties': {'Tag': facelabel}} self.face = self.raw['MeshTri3']['Data'] self.facelabel = self.raw['MeshTri3']['Properties']['Tag'] else: @@ -99,8 +94,9 @@ def from_filename(self, filename, opt={}, **kwargs): def to_filename(self, filename, opt={}, **kwargs): write(self, filename, opt, **kwargs) + def read(filename, opt={}, **kwargs): - """ Load a JSON or binary JData (BJData) based JMesh file + """Load a JSON or binary JData (BJData) based JMesh file Parameters ---------- @@ -116,73 +112,90 @@ def read(filename, opt={}, **kwargs): mesh : a JMesh object Return a JMesh object containing mesh data fields such as node, face, nodelabel etc """ - opt.setdefault('ndarray',True) + opt.setdefault('ndarray', True) mesh = JMesh mesh.raw = jdload(filename, opt, **kwargs) - #-------------------------------------------------- + # -------------------------------------------------- # read metadata as `info` - #-------------------------------------------------- - if('_DataInfo_' in mesh.raw): + # -------------------------------------------------- + if '_DataInfo_' in mesh.raw: mesh.info = mesh.raw['_DataInfo_'] - #-------------------------------------------------- + # -------------------------------------------------- # read vertices as `node` and `nodelabel` - #-------------------------------------------------- - if('MeshVertex3' in mesh.raw): + # -------------------------------------------------- + if 'MeshVertex3' in mesh.raw: mesh.node = mesh.raw['MeshVertex3'] - elif('MeshNode' in mesh.raw): + elif 'MeshNode' in mesh.raw: mesh.node = mesh.raw['MeshNode'] else: raise Exception('JMesh', 'JMesh surface must contain node (MeshVertex3 or MeshNode)') - if(isinstance(mesh.node, dict)): - if(('Properties' in mesh.node) and ('Tag' in mesh.node['Properties'])): + if isinstance(mesh.node, dict): + if ('Properties' in mesh.node) and ('Tag' in mesh.node['Properties']): mesh.nodelabel = mesh.node['Properties']['Tag'] - if('Data' in mesh.node): + if 'Data' in mesh.node: mesh.node = mesh.node['Data'] - if(isinstance(mesh.node, np.ndarray) and mesh.node.ndim == 2 and mesh.node.shape[1] > 3): - mesh.nodelabel = mesh.node[:,3:] + if isinstance(mesh.node, np.ndarray) and mesh.node.ndim == 2 and mesh.node.shape[1] > 3: + mesh.nodelabel = mesh.node[:, 3:] mesh.node = mesh.node[:, 0:3] - #-------------------------------------------------- + # -------------------------------------------------- # read triangles as `face` and `facelabel` - #-------------------------------------------------- - if('MeshTri3' in mesh.raw): + # -------------------------------------------------- + if 'MeshTri3' in mesh.raw: mesh.face = mesh.raw['MeshTri3'] - elif('MeshSurf' in mesh.raw): + elif 'MeshSurf' in mesh.raw: mesh.face = mesh.raw['MeshSurf'] - if(isinstance(mesh.face, dict)): - if(('Properties' in mesh.face) and ('Tag' in mesh.face['Properties'])): + if isinstance(mesh.face, dict): + if ('Properties' in mesh.face) and ('Tag' in mesh.face['Properties']): mesh.facelabel = mesh.face['Properties']['Tag'] - if('Data' in mesh.face): + if 'Data' in mesh.face: mesh.face = mesh.face['Data'] - if(isinstance(mesh.face, np.ndarray) and mesh.face.ndim == 2 and mesh.face.shape[1] > 3): - mesh.facelabel = mesh.face[:,3:] + if isinstance(mesh.face, np.ndarray) and mesh.face.ndim == 2 and mesh.face.shape[1] > 3: + mesh.facelabel = mesh.face[:, 3:] mesh.face = mesh.face[:, 0:3] - #-------------------------------------------------- + # -------------------------------------------------- # convert to numpy ndarray - #-------------------------------------------------- - if(opt['ndarray']): - if hasattr(mesh, 'node') and (not mesh.node is None) and (not isinstance(mesh.node, np.ndarray)): + # -------------------------------------------------- + if opt['ndarray']: + if ( + hasattr(mesh, 'node') + and (not mesh.node is None) + and (not isinstance(mesh.node, np.ndarray)) + ): mesh.node = np.array(mesh.node) - if hasattr(mesh, 'face') and (not mesh.face is None) and (not isinstance(mesh.face, np.ndarray)): + if ( + hasattr(mesh, 'face') + and (not mesh.face is None) + and (not isinstance(mesh.face, np.ndarray)) + ): mesh.face = np.array(mesh.face) - if hasattr(mesh, 'nodelabel') and (not mesh.nodelabel is None) and (not isinstance(mesh.nodelabel, np.ndarray)): + if ( + hasattr(mesh, 'nodelabel') + and (not mesh.nodelabel is None) + and (not isinstance(mesh.nodelabel, np.ndarray)) + ): mesh.nodelabel = np.array(mesh.nodelabel) - if hasattr(mesh, 'facelabel') and (not mesh.facelabel is None) and (not isinstance(mesh.facelabel, np.ndarray)): + if ( + hasattr(mesh, 'facelabel') + and (not mesh.facelabel is None) + and (not isinstance(mesh.facelabel, np.ndarray)) + ): mesh.facelabel = np.array(mesh.facelabel) return mesh + def write(mesh, filename, opt={}, **kwargs): - """ Save the current mesh to a new file + """Save the current mesh to a new file Parameters ---------- @@ -207,20 +220,21 @@ def write(mesh, filename, opt={}, **kwargs): mesh.raw = {} if hasattr(mesh, 'info') and not mesh.info is None: - mesh.raw['_DataInfo_']=mesh.info + mesh.raw['_DataInfo_'] = mesh.info if hasattr(mesh, 'node') and not mesh.node is None: - if(hasattr(mesh, 'facelabel') and not mesh.nodelabel is None): - mesh.raw['MeshVertex3']={'Data': mesh.node, 'Properties': {'Tag': mesh.nodelabel}} + if hasattr(mesh, 'facelabel') and not mesh.nodelabel is None: + mesh.raw['MeshVertex3'] = {'Data': mesh.node, 'Properties': {'Tag': mesh.nodelabel}} else: - mesh.raw['MeshVertex3']=mesh.node + mesh.raw['MeshVertex3'] = mesh.node if hasattr(mesh, 'info') and not mesh.face is None: - if(hasattr(mesh, 'facelabel') and not mesh.facelabel is None): - mesh.raw['MeshTri3']={'Data': mesh.face, 'Properties': {'Tag': mesh.facelabel}} + if hasattr(mesh, 'facelabel') and not mesh.facelabel is None: + mesh.raw['MeshTri3'] = {'Data': mesh.face, 'Properties': {'Tag': mesh.facelabel}} else: - mesh.raw['MeshTri3']=mesh.face + mesh.raw['MeshTri3'] = mesh.face return jdsave(mesh.raw, filename, opt, **kwargs) + load = read save = write From 69669b4a0fff31dac6797d09827cfbc2d90b1f64 Mon Sep 17 00:00:00 2001 From: Qianqian Fang Date: Sun, 19 Feb 2023 13:36:36 -0500 Subject: [PATCH 3/5] add dependencies to run ci --- requirements.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/requirements.txt b/requirements.txt index 1d1e434609..6d4de8bcc2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,3 +2,5 @@ numpy >=1.19 packaging >=17 setuptools +jdata +bjdata From 86be7c292908fe7d6240395bf52b876777a4ce70 Mon Sep 17 00:00:00 2001 From: Qianqian Fang Date: Sat, 25 Feb 2023 15:35:14 -0500 Subject: [PATCH 4/5] fix flake8 warnings --- nibabel/jmesh/jmesh.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/nibabel/jmesh/jmesh.py b/nibabel/jmesh/jmesh.py index 716d266e7c..cf26d8c504 100644 --- a/nibabel/jmesh/jmesh.py +++ b/nibabel/jmesh/jmesh.py @@ -66,10 +66,10 @@ class JMesh(FileBasedImage): def __init__(self, info=None, node=None, nodelabel=None, face=None, facelabel=None): self.raw = {} - if not info is None: + if info is not None: self.raw['_DataInfo_'] = info - if not nodelabel is None: + if nodelabel is not None: self.raw['MeshVertex3'] = {'Data': node, 'Properties': {'Tag': nodelabel}} self.node = self.raw['MeshVertex3']['Data'] self.nodelabel = self.raw['MeshVertex3']['Properties']['Tag'] @@ -77,7 +77,7 @@ def __init__(self, info=None, node=None, nodelabel=None, face=None, facelabel=No self.raw['MeshVertex3'] = node self.node = self.raw['MeshVertex3'] - if not facelabel is None: + if facelabel is not None: self.raw['MeshTri3'] = {'Data': face, 'Properties': {'Tag': facelabel}} self.face = self.raw['MeshTri3']['Data'] self.facelabel = self.raw['MeshTri3']['Properties']['Tag'] @@ -165,28 +165,28 @@ def read(filename, opt={}, **kwargs): if opt['ndarray']: if ( hasattr(mesh, 'node') - and (not mesh.node is None) + and (mesh.node is not None) and (not isinstance(mesh.node, np.ndarray)) ): mesh.node = np.array(mesh.node) if ( hasattr(mesh, 'face') - and (not mesh.face is None) + and (mesh.face is not None) and (not isinstance(mesh.face, np.ndarray)) ): mesh.face = np.array(mesh.face) if ( hasattr(mesh, 'nodelabel') - and (not mesh.nodelabel is None) + and (mesh.nodelabel is not None) and (not isinstance(mesh.nodelabel, np.ndarray)) ): mesh.nodelabel = np.array(mesh.nodelabel) if ( hasattr(mesh, 'facelabel') - and (not mesh.facelabel is None) + and (mesh.facelabel is not None) and (not isinstance(mesh.facelabel, np.ndarray)) ): mesh.facelabel = np.array(mesh.facelabel) @@ -219,16 +219,16 @@ def write(mesh, filename, opt={}, **kwargs): if not hasattr(mesh, 'raw') or mesh.raw is None: mesh.raw = {} - if hasattr(mesh, 'info') and not mesh.info is None: + if hasattr(mesh, 'info') and mesh.info is not None: mesh.raw['_DataInfo_'] = mesh.info - if hasattr(mesh, 'node') and not mesh.node is None: - if hasattr(mesh, 'facelabel') and not mesh.nodelabel is None: + if hasattr(mesh, 'node') and mesh.node is not None: + if hasattr(mesh, 'facelabel') and mesh.nodelabel is not None: mesh.raw['MeshVertex3'] = {'Data': mesh.node, 'Properties': {'Tag': mesh.nodelabel}} else: mesh.raw['MeshVertex3'] = mesh.node - if hasattr(mesh, 'info') and not mesh.face is None: - if hasattr(mesh, 'facelabel') and not mesh.facelabel is None: + if hasattr(mesh, 'info') and mesh.face is not None: + if hasattr(mesh, 'facelabel') and mesh.facelabel is not None: mesh.raw['MeshTri3'] = {'Data': mesh.face, 'Properties': {'Tag': mesh.facelabel}} else: mesh.raw['MeshTri3'] = mesh.face From 2c8942f3b34c8545a7093601d480f2dc06d79286 Mon Sep 17 00:00:00 2001 From: Qianqian Fang Date: Sat, 25 Feb 2023 15:41:11 -0500 Subject: [PATCH 5/5] fix ci dependency errors --- min-requirements.txt | 4 +++- pyproject.toml | 2 ++ requirements.txt | 6 +++--- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/min-requirements.txt b/min-requirements.txt index 305f16dcbd..8e2715d00b 100644 --- a/min-requirements.txt +++ b/min-requirements.txt @@ -1,4 +1,6 @@ # Auto-generated by tools/update_requirements.py numpy ==1.19 packaging ==17 -setuptools +importlib_resources; python_version < '3.9' +jdata ==0.5 +bjdata ==0.4 diff --git a/pyproject.toml b/pyproject.toml index f944f8e685..97fded74ec 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,6 +14,8 @@ dependencies = [ "numpy >=1.19", "packaging >=17", "importlib_resources; python_version < '3.9'", + "jdata >=0.5", + "bjdata >=0.4", ] classifiers = [ "Development Status :: 5 - Production/Stable", diff --git a/requirements.txt b/requirements.txt index 6d4de8bcc2..6727bb0e4a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ # Auto-generated by tools/update_requirements.py numpy >=1.19 packaging >=17 -setuptools -jdata -bjdata +importlib_resources; python_version < '3.9' +jdata >=0.5 +bjdata >=0.4