Saving and loading in a JSON + NumPy zip container (panels.json_io)#

The objects Shell, StiffPanelBay, with its stiffeners BladeStiff1D and BladeStiff2D, and MultiDomain are saved to and loaded from a zip file with:

from panels import Shell
from panels.shell import load

s = Shell(a=1., b=0.5, stack=[0, 90, 90, 0], plyt=1e-3,
          laminaprop=(71e9, 0.33), m=8, n=8)
s.name = 'plate'
s.save()              # writes plate.shell.zip
s2 = load('plate')    # or load('plate.shell.zip')

or with the functions save() and load() of this module, which handle the three classes. Instead of a file name, both accept a binary file object, e.g. io.BytesIO, which is how a browser application running on Pyodide saves without a file system:

import io
buf = io.BytesIO()
s.save(buf)
data = buf.getvalue()  # bytes, e.g. offered for download

The file is a zip archive, compressed with ZIP_DEFLATED, containing:

  • model.json: the inputs, such as the geometry, the number of terms m and n, the boundary conditions, the stacking sequence, the ply thicknesses, the lamina properties and the loads, in the envelope:

    {
      "type": "Shell",
      "format_version": 1,
      "panels_version": "0.13.11",
      "data": {...}
    }
    
  • arrays/<key>.npy: every NumPy array, e.g. the constitutive matrices ABDnxny and the results fields or results['eigvecs'], written by numpy.save() with allow_pickle=False. In model.json an array is replaced by {"__ndarray__": "arrays/<key>.npy"}.

The laminates, e.g. Shell.lam, are embedded in model.json with composites.to_dict(). The JSON is strict, readable by JSON.parse in JavaScript: the floats nan, inf and -inf are stored as the strings "NaN", "Infinity" and "-Infinity". Tuples are loaded as lists and NumPy scalars as Python int or float.

Only an explicit list of attributes of each class is stored, such that the format does not depend on implementation details. Saving an attribute whose value is not supported raises TypeError, e.g. the functions of the distributed loads Shell.add_distr_load_fixed_x() or of a pressure p(x, y). The following are not stored and are recomputed on demand: the structural matrices (Shell.matrices, StiffPanelBay.kC, MultiDomain.kC, MultiDomain.T, …), the number of threads out_num_cores, which takes the default of the machine that loads the file, and the attributes of Python subclasses, the loaded object having the type of the base class.

Loading is safe for files from untrusted sources, unlike pickle: the arrays are read with allow_pickle=False, the members are read in memory and never extracted, only the members referenced by model.json are read, after checking that their uncompressed sizes do not exceed max_size in total, and unknown keys, missing or extra members and newer format versions raise ValueError.

The pickle files written by older versions of panels are not loaded, since a pickle file can execute arbitrary code. One from a trusted source can be converted by loading it with pickle.load() and saving the object again.

panels.json_io.save(obj, fname)#

Save an object to a zip file

Parameters:
objShell, StiffPanelBay or MultiDomain

The object to be saved. It is not modified.

fnamestr, path-like or file object

Name of the file, or a binary file object opened for writing, e.g. io.BytesIO.

Raises:
TypeError

If obj is not one of the supported classes, or if one of its stored attributes has a value that cannot be saved, e.g. a function.

panels.json_io.load(fname, max_size=4294967296)#

Load an object from a zip file created by save()

Parameters:
fnamestr, path-like or file object

Name of the file, or a binary file object opened for reading, e.g. io.BytesIO.

max_sizeint, optional

Maximum total uncompressed size of the members read, in bytes, 4 GiB by default. It is checked before reading, against the sizes declared in the zip file.

Returns:
objShell, StiffPanelBay or MultiDomain

The object.

Raises:
ValueError

If the file is not a zip file saved by panels, e.g. a pickle file of an older version, is not valid, has unknown keys, missing or extra members, exceeds max_size, or was saved by a newer format version.