
     iW                     v    d Z ddlZddlZddlZddlZddlmZ ddlmZ ddlmZ d Z	 G d d	e
          Zd
 ZdS )a  
Core functionality for storing n-D grids
========================================

The :mod:`core` module contains classes and functions that are
independent of the grid data format. In particular this module
contains the :class:`Grid` class that acts as a universal constructor
for specific formats::

 g = Grid(**kwargs)           # construct
 g.export(filename, format)   # export to the desired format

Some formats can also be read::

 g = Grid()                   # make an empty Grid
 g.load(filename)             # populate with data from filename


Classes
-------

.. autoclass:: Grid
   :members:
   :undoc-members:
   :show-inheritance:

Functions
---------

.. autofunction:: ndmeshgrid
    N   )OpenDX)gOpenMol)mrcc                 6    	 | j         S # t          $ r | cY S w xY w)zJAccess the underlying ndarray of a Grid object or return the object itself)gridAttributeError)xs    W/srv/www/vhosts/g4struct/public_html/venv/lib/python3.11/site-packages/gridData/core.py_gridr   2   s2    v   s   	 c                      e Zd ZdZdZ	 	 	 d4dZed             Zej        d             Zd	 Z	d
 Z
d Zed             Zd5dZd5dZd5dZd5dZd5dZd6dZd5dZd5dZ	 	 	 	 	 d7dZd8dZd Zd9dZd Zd Zd:dZd Zd;dZd  Zd! Zd" Z d# Z!d<d$Z"d% Z#d& Z$d' Z%d( Z&d) Z'd* Z(d+ Z)d, Z*d- Z+d. Z,d/ Z-d0 Z.d1 Z/d2 Z0d3 Z1dS )=Grida  A multidimensional grid object with origin and grid spacings.

    :class:`Grid` objects can be used in arithmetical calculations
    just like numpy arrays *if* they are compatible, i.e., they have
    the same shapes and lengths. In order to make arrays compatible,
    they an be resampled (:meth:`resample`) on a common grid.

    The attribute :attr:`grid` that holds the data is a standard numpy
    array and so the data can be directly manipulated.

    Data can be read from a number of molecular volume/density formats
    and written out in different formats with :meth:`export`.


    Parameters
    ----------
    grid : numpy.ndarray or str (optional)
      Build the grid either from a histogram or density (a numpy nD
      array) or read data from a filename.

    edges : list (optional)
      List of arrays, the lower and upper bin edges along the axes
      (same as the output by :func:`numpy.histogramdd`)

    origin : :class:`numpy.ndarray` (optional)
      Cartesian coordinates of the center of grid position at index
      ``[0, 0, ..., 0]``.

    delta : :class:`numpy.ndarray` (optional)
      Either ``n x n`` array containing the cell lengths in each dimension,
      or ``n x 1`` array for rectangular arrays.

    metadata : dict (optional)
      A user defined dictionary of arbitrary key/value pairs
      associated with the density; the class does not touch
      :attr:`metadata` but stores it with :meth:`save`

    interpolation_spline_order : int (optional)
      Order of interpolation function for resampling with
      :func:`resample`; cubic splines = 3 and the default is 3

    file_format : str (optional)
      Name of the file format; only necessary when `grid` is a
      filename (see :meth:`load`) and autodetection of the file
      format fails. The default is ``None`` and normally the file
      format is guessed from the file extension.

    assume_volumetric : bool (optional)
      If ``False`` (default), check the file header to determine whether
      the data in `grid` is a 3D volume. If ``True``, assume `grid` is volumetric.

      .. Note:: `assume_volumetric` only has an effect when loading
         MRC/CCP4 files. See :class:`gridData.mrc.MRC`

      .. versionadded:: 1.1.0

    Raises
    ------
    TypeError
      If the dimensions of the various input data do not agree with
      each other.
    ValueError
      If some of the required data are not provided in the keyword
      arguments, e.g., if only the `grid` is supplied as an array but
      not the `edges` or only `grid` and one of `origin` and `delta`.
    NotImplementedError
      If triclinic (non-orthorhombic) boxes are supplied in `delta`

      .. Note:: `delta` can only be a 1D array of length :attr:`grid.ndim`


    Attributes
    ----------
    grid : :class:`numpy.ndarray`
      This array can be any number of dimensions supported by NumPy
      in order to represent high-dimensional data. When used with
      data that represents real space densities then the **axis
      convention in GridDataFormats** is that axis 0 corresponds to
      the Cartesian :math:`x` component, axis 1 corresponds to the
      :math:`y` component, and axis 2 to the :math:`z` component.

    delta : :class:`numpy.ndarray`
      Length of a grid cell (spacing or voxelsize) in :math:`x`,
      :math:`y`, :math:`z` dimensions. This is a *1D array* with
      length :attr:`Grid.grid.ndim`.

    origin : :class:`numpy.ndarray`
      Array with the Cartesian coordinates of the coordinate system
      origin, the *center* of cell ``Grid.grid[0, 0, .., 0]``.

    edges : list
      List of arrays, one for each axis in :attr:`grid`.  Each 1D edge
      array describes the *edges* of the grid cells along the
      corresponding axis. The length of an edge array for axis ``i``
      is ``grid.shape[i] + 1`` because it contains the lower boundary
      for the first cell, the boundaries between all grid cells, and
      the upper boundary for the last cell. The edges are assumed to
      be regular with spacing indicated in :attr:`delta`, namely
      ``Grid.delta[i]`` for axis ``i``.

    midpoints : list
      List of arrays, one for each axis in :attr:`grid`.  Each 1D
      midpoints array contains the *midpoints* of the grid cells along
      the corresponding axis.

    metadata : dict
      A user-defined dictionary that can be used to annotate the
      data. The content is not touched by :class:`Grid`. It is saved
      together with the other data with :meth:`save`.


    Example
    -------
    Create a Grid object from data.

    From :func:`numpy.histogramdd`::

      grid, edges = numpy.histogramdd(...)
      g = Grid(grid, edges=edges)

    From an arbitrary grid::

      g = Grid(grid, origin=origin, delta=delta)

    From a saved file::

      g = Grid(filename)

    or ::

      g = Grid()
      g.load(filename)


    Notes
    -----
    In principle, the dimension (number of axes) is arbitrary but in
    practice many formats only support three and almost all
    functionality is only tested for this special case.

    The :meth:`export` method with ``format='dx'`` always exports a 3D
    object. Other methods might work for an array of any dimension (in
    particular the Python pickle output).


    .. versionchanged:: 0.5.0
       New *file_format* keyword argument.

    .. versionchanged:: 0.7.0
       CCP4 files are now read with :class:`gridData.mrc.MRC` and not anymore
       with the deprecated/buggy `ccp4.CCP4`

    DXN   Fc	                 X   | j         | j        | j        | j        | j        d| _        | j        | j        | j        | j        | j        | j        | j        d| _        ||ni | _	        d | _
        || _        d | _        |t          |t                    r|}	n`	 t          t          |          d          5  	 d d d            n# 1 swxY w Y   t          |          }	n# t           t"          f$ r d }	Y nw xY w|	|                     |	||           d S |                     |||||           d S d S )N)r   PKLPICKLEPYTHONMRC)CCP4r   r   PLTr   r   r   rb)file_formatassume_volumetric)
_export_dx_export_python_export_mrc
_exporters	_load_mrc_load_dx	_load_plt_load_python_loadersmetadata_Grid__interpolated!_Grid__interpolation_spline_orderinterpolation_cval
isinstancestropenOSErrorIOErrorload_load)
selfr   edgesorigindeltar$   interpolation_spline_orderr   r   filenames
             r   __init__zGrid.__init__   s   
 /&))#
 
 NN->$''
 
 %-$8b",F)"&$$$ )) c$ii..                  #4yyHH  ) $ $ $#HHH$ #		(O`	aaaaa

4&%@@@@@+ s6   C 1B?3C ?CC CC C0/C0c                     | j         S )zOrder of the B-spline interpolation of the data.

        3 = cubic; 4 & 5 are also supported

        Only choose values that are acceptable to
        :func:`scipy.ndimage.spline_filter`!

        See Also
        --------
        interpolated
        )r&   r/   s    r   r3   zGrid.interpolation_spline_order	  s     00    c                 <    || _         |                                  dS )a  Setting the ``interpolation_spline_order`` updates :func:`interpolated`

        Because we cache the interpolation function, we need to rebuild the
        cache whenever the interpolation order changes: this is
        handled by :meth:`_update`

        N)r&   _update)r/   r
   s     r   r3   zGrid.interpolation_spline_order  s     -.)r8   c                     	 |j         }n# t          $ r Y nw xY w|                     |          }t          | } | j        | }|                     ||          S )a/  Resample data to a new grid with edges *edges*.

        This method creates a new grid with the data from the current
        grid resampled to a regular grid specified by `edges`.  The
        order of the interpolation is set by
        :attr:`Grid.interpolation_spline_order`: change the value
        *before* calling :meth:`resample`.

        Parameters
        ----------
        edges : tuple of arrays or Grid
             edges of the new grid or a :class:`Grid` instance that
             provides :attr:`Grid.edges`

        Returns
        -------
        Grid
             a new :class:`Grid` with the data interpolated over the
             new grid cells


        Examples
        --------

        Providing `edges` (a tuple of three arrays, indicating the
        boundaries of each grid cell)::

          g = grid.resample(edges)

        As a convenience, one can also supply another :class:`Grid` as
        the argument for this method ::

          g = grid.resample(othergrid)

        and the edges are taken from :attr:`Grid.edges`.

        )r0   r	   
_midpoints
ndmeshgridinterpolated	__class__)r/   r0   	midpointscoordinatesnewgrids        r   resamplezGrid.resample%  so    L	KEE 	 	 	D	OOE**	 ),#$#[1~~gu---s   
 
c           
      \   t          |          dk    rt          d          t          j        |                                           t          j        |                                           z
  dt          j        |                                           z   z  }|t          |          z  }t          j        |                                           }|dddf         |dddf         z
  t          j        dt          j	        |dddf         |dddf         z
  |z                      z  }dt          j
        |dddf         |dddf         z
  |z            z   }d t          |dddf         d|z  z
  |dddf         d|z  z   |          D             }|                     |          S )	a  Resample to a new regular grid.


        Parameters
        ----------
        factor : float
            The number of grid cells are scaled with `factor` in each
            dimension, i.e., ``factor * N_i`` cells along each
            dimension i. Must be positive, and cannot result in fewer
            than 2 cells along a dimension.


        Returns
        -------
        interpolated grid : Grid
            The resampled data are represented on a :class:`Grid` with the new
            grid cell sizes.

        See Also
        --------
        resample


        .. versionchanged:: 0.6.0
           Previous implementations would not alter the range of the grid edges
           being resampled on. As a result, values at the grid edges would creep
           steadily inward. The new implementation recalculates the extent of
           grid edges for every resampling.

        r   zFactor must be positiveNr      c           	      `    g | ]+\  }}}t          j        ||t          |          d           ,S )T)numendpoint)numpylinspaceint).0startstopNs       r   
<listcomp>z(Grid.resample_factor.<locals>.<listcomp>  sL     d d dL\UTXZ[tQ$GGG d d dr8         ?)float
ValueErrorrJ   array
_max_edges
_min_edges
_len_edgesr<   maximumfloorroundziprC   )r/   factorspacing
newspacing
smidpoints
edgelengthr0   s          r   resample_factorzGrid.resample_factorU  s   > ==A6777;t0011EK@Q@Q4R4RRu{4??#4#45557 uV}},
[!2!233
 !B'*QQQT*::u}u{Jqqq"u-
111a40@@JNOO@Q @Q R
 KAAArE*Z1-==KLLM
d d`cqqq!tsZ//AAArE1BS:EU1UWaac ac d d d}}U###r8   c                 p   t          j        t          t          d | j                                      | _        |                     | j                  | _        t          j        t          t          d | j                                      | _        | j	        | 
                                | _	        dS dS )a  compute/update all derived data

        Can be called without harm and is idem-potent.

        Updates these attributes and methods:
           :attr:`origin`
              the center of the cell with index 0,0,0
           :attr:`midpoints`
              centre coordinate of each grid cell
           :meth:`interpolated`
              spline interpolation function that can generated a value for
              coordinate
        c                 J    | d         | d         z
  t          |           dz
  z  S )NrE   r   r   )lenes    r   <lambda>zGrid._update.<locals>.<lambda>  s!    1R51Q4<CFFQJ7 r8   c                     | d         S )Nr    )ms    r   rh   zGrid._update.<locals>.<lambda>  s
    QqT r8   N)rJ   rU   listmapr0   r2   r<   r@   r1   r%   _interpolationFunctionFactoryr7   s    r   r:   zGrid._update  s     [77DD"F "F G G
44k$s>>4>'J'J"K"KLL*"&"D"D"F"FD +*r8   c                 P    | j         |                                 | _         | j         S )a  B-spline function over the data grid(x,y,z).

        The :func:`interpolated` function allows one to obtain data
        values for any values of the coordinates::

           interpolated([x1,x2,...],[y1,y2,...],[z1,z2,...]) -> F[x1,y1,z1],F[x2,y2,z2],...

        The interpolation order is set in
        :attr:`Grid.interpolation_spline_order`.

        The interpolated function is computed once and is cached for better
        performance. Whenever :attr:`~Grid.interpolation_spline_order` is
        modified, :meth:`Grid.interpolated` is recomputed.

        The value for unknown data is set in :attr:`Grid.interpolation_cval`
        (TODO: also recompute when ``interpolation_cval`` value is changed.)

        Example
        -------
        Example usage for resampling::

           XX, YY, ZZ = numpy.mgrid[40:75:0.5, 96:150:0.5, 20:50:0.5]
           FF = interpolated(XX, YY, ZZ)

        Note
        ----
        Values are interpolated with a spline function. It is possible
        that the spline will generate values that would not normally
        appear in the data. For example, a density is non-negative but
        a cubic spline interpolation can generate negative values,
        especially at the boundary between 0 and high values.

        Internally, the function uses :func:`scipy.ndimage.map_coordinates`
        with ``mode="constant"`` whereby interpolated values outside
        the interpolated grid are determined by filling all values beyond
        the edge with the same constant value, defined by the
        :attr:`interpolation_cval` parameter, which when not set defaults
        to the minimum value in the interpolated grid.


        .. versionchanged:: 0.6.0
           Interpolation outside the grid is now performed with
           ``mode="constant"`` rather than ``mode="nearest"``, eliminating
           extruded volumes when interpolating beyond the grid.

        )r%   rn   r7   s    r   r>   zGrid.interpolated  s+    ` &"&"D"D"F"FD""r8   c                 2    || j         }fd|D             S )Nc                 &    g | ]} |          S rj   rj   )rM   rg   funcs     r   rQ   z#Grid._map_edges.<locals>.<listcomp>  s!    '''AQ'''r8   r0   )r/   rr   r0   s    ` r   
_map_edgeszGrid._map_edges  s)    =JE''''''''r8   c                 2    |                      d |          S )Nc                 2    d| d d         | dd          z   z  S )NrR   rE   r   rj   rf   s    r   rh   z!Grid._midpoints.<locals>.<lambda>  s    #2#122)? r8   rs   )rt   r/   r0   s     r   r<   zGrid._midpoints  s    ??uMMMr8   c                 :    |                      t          |          S Nrs   )rt   re   rw   s     r   rX   zGrid._len_edges  s    s%000r8   c                 D    |                      t          j        |          S ry   )rt   rJ   minrw   s     r   rW   zGrid._min_edges      uy666r8   c                 D    |                      t          j        |          S ry   )rt   rJ   maxrw   s     r   rV   zGrid._max_edges  r|   r8   Tc                    |r| j         }n| j        }|ut          j                            |          }|d         dd          dv r4t          j                            |d                   d         dd          }n|d         dd          }|                                }|s| j        }||vr5t          d                    ||	                                                    |S )Nr   )gzr   z.File format {} not available, choose one of {})
r   r#   ospathsplitextupperdefault_formatrT   formatkeys)r/   r4   r   export	availablesplitteds         r   _guess_formatzGrid._guess_format  s     	&IIIw''11H{122(** g..x{;;A>qrrB&qk!""o!'')) 	.-Ki''@GG!1!13 34 4 4 r8   c                 H    | j         |                     ||d                   S )NTr   r   )r   r   r/   r4   r   s      r   _get_exporterzGrid._get_exporter  s2    t11(>I9=  2  ?  ? @ 	@r8   c                 H    | j         |                     ||d                   S )NFr   )r#   r   r   s      r   _get_loaderzGrid._get_loader  s0    }T//<G7< 0 > > ? 	?r8   c                    |6t          j        |          | _        || _        |                                  d S $!t          j                  t          j                  t                    |j        k    rt          d          j        dk    r1t          j	                  rt          j
        |j                  z  nAj        dk    rt          d          t                    |j        k    rt          d          fdt          |j                  D             | _        t          j        |          | _        |                                  d S t          d                    ||                    )Nz6Dimension of origin is not the same as grid dimension.rj   r   z(Non-rectangular grids are not supported.z5delta should be scalar or array-like oflen(grid.ndim)c                 n    g | ]1\  }}|         t          j        |d z             dz
  |         z  z   2S )r   rR   )rJ   arange)rM   dimrk   r2   r1   s      r   rQ   zGrid._load.<locals>.<listcomp>  sV     ? ? ?$c1 !+ <A..4c
BC ? ? ?r8   zWrong/missing data to set up Grid. Use Grid() or Grid(grid=<array>, edges=<list>) or Grid(grid=<array>, origin=(x0, y0, z0), delta=(dx, dy, dz)):
grid={0} edges={1} origin={2} delta={3})rJ   
asanyarrayr   r0   r:   re   ndim	TypeErrorshapeisrealonesNotImplementedError	enumeraterT   r   )r/   r   r0   r$   r1   r2   s       ``r   r.   z
Grid._load  s    (..DIDJLLNNNNNE$5%f--F$U++E6{{di''LN N N{b  U\%%8%8 
49--5a)>@ @ @Uty(( !1 2 2 2? ? ? ? ?(1$*(=(=? ? ?DJ (..DILLNNNNN: ;A&%;0 ;0	1 1 1r8   c                     t          |          }t          j                            |          st	          t
          j        d|          |                     ||          } |||           dS )zLoad saved grid and edges from `filename`

        The :meth:`load` method calls the class's constructor method and
        completely resets all values, based on the loaded data.
        zfile not foundr   r   N)r)   r   r   existsr,   errnoENOENTr   )r/   r4   r   r   loaders        r   r-   z	Grid.load,  sq     x==w~~h'' 	D %,(8(CCC!!(!DDx+<======r8   c                     t          |d          5 }t          j        |          }d d d            n# 1 swxY w Y   |                     |d         |d         |d                    d S )Nr   r   r0   r$   r   r0   r$   )r*   pickler-   r.   )r/   r4   kwargsfsaveds        r   r"   zGrid._load_python;  s    (D!! 	#QKNNE	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	#

fw!*- 	 	/ 	/ 	/ 	/ 	/s   266c                     t          j        ||          }|                                \  }}|                     ||| j                   |j                                        | _        dS )z&Initializes Grid from a MRC/CCP4 file.r   r   N)r   r   histogramddr.   r$   headercopy_mrc_header)r/   r4   r   r   mrcfiler   r0   s          r   r   zGrid._load_mrcB  sd    '(6GHHH))++e

EDM
BBB #>..00r8   c                     t          j        d          }|                    |           |                                \  }}|                     ||| j                   dS )z$Initializes Grid from a OpenDX file.r   r   N)r   fieldreadr   r.   r$   )r/   r4   r   dxr   r0   s         r   r    zGrid._load_dxK  sT    \!__
nn&&e

EDM
BBBBBr8   c                     t          j                    }|                    |           |                                \  }}|                     ||| j                   dS )z'Initialize Grid from gOpenMol plt file.r   N)r   Pltr   r   r.   r$   )r/   r4   r   gr   r0   s         r   r!   zGrid._load_pltR  sP    LNN	xmmooe

EDM
BBBBBr8   "c                 n    t          |          }|                     ||          } ||||           dS )a  export density to file using the given format.

        The format can also be deduced from the suffix of the filename
        although the `file_format` keyword takes precedence.

        The default format for :meth:`export` is 'dx'.  Use 'dx' for
        visualization.

        Implemented formats:

        dx
            :mod:`OpenDX`
        mrc
            :mod:`mrc` MRC/CCP4 format
        pickle
            pickle (use :meth:`Grid.load` to restore); :meth:`Grid.save`
            is simpler than ``export(format='python')``.

        Parameters
        ----------
        filename : str
            name of the output file

        file_format : {'dx', 'pickle', 'mrc', None} (optional)
            output file format, the default is "dx"

        type : str (optional)
            for DX, set the output DX array type, e.g., "double" or "float".
            By default (``None``), the DX type is determined from the numpy
            dtype of the array of the grid (and this will typically result in
            "double").

            .. versionadded:: 0.4.0

        typequote : str (optional)
            For DX, set the character used to quote the type string;
            by default this is a double-quote character, '"'.
            Custom parsers like the one from NAMD-GridForces (backend for MDFF)
            expect no quotes, and typequote='' may be used to appease them.

            .. versionadded:: 0.5.0

        r   type	typequoteN)r)   r   )r/   r4   r   r   r   exporters         r   r   zGrid.exportY  sE    X x==%%hK%HH	::::::r8   c                     t          | j        | j        | j                  }t	          |d          5 }t          j        ||t
          j                   ddd           dS # 1 swxY w Y   dS )zPickle the Grid object

        The object is dumped as a dictionary with grid and edges: This
        is sufficient to recreate the grid object with ``__init__()``.
        r   wbN)dictr   r0   r$   r*   r   dumpHIGHEST_PROTOCOL)r/   r4   r   datar   s        r   r   zGrid._export_python  s     $*t}MMM(D!! 	:QKa!8999	: 	: 	: 	: 	: 	: 	: 	: 	: 	: 	: 	: 	: 	: 	: 	: 	: 	:s   !A  A$'A$c           
         t           j                            |          \  }}|dz   }g d}| j        r|                    d           | j        D ]E}|                    dt          |          z   dz   t          | j        |                   z              F|                    d           t          t          j        d| j	        j
        | j        | j                  t          j        d| j	        j
                  t          j        d	| j	        ||
                    }	t          j        d|	|          }
|dk    r||z   }|
                    |           dS )aT  Export the density grid to an OpenDX file.

        The file format is the simplest regular grid array and it is
        also understood by VMD's and Chimera's DX reader; PyMOL
        requires the dx `type` to be set to "double".

        For the file format see
        http://opendx.sdsc.edu/docs/html/pages/usrgu068.htm#HDREDF

        z.dx)z<OpenDX density file written by gridDataFormats.Grid.export()zGFile format: http://opendx.sdsc.edu/docs/html/pages/usrgu068.htm#HDREDFz?Data are embedded in the header and tied to the grid positions.zFData is written in C array order: In grid[x,y,z] the axis z is fastestz>varying, then y, then finally x, i.e. z is the innermost loop.z-Meta data stored with the python Grid object:z   z = z<(Note: the VMD dx-reader chokes on comments below this line)r   rF   r   r   )	positionsconnectionsr   density)
componentscommentsz.gzN)r   r   r   r$   appendr)   r   r   gridpositionsr   r   r1   r2   gridconnectionsrU   r   write)r/   r4   r   r   r   rootextr   kr   r   s              r   r   zGrid._export_dx  sf    G$$X..	c%<N N N = 	MOOKLLL 	L 	LAOOECFFNU2Sq9I5J5JJKKKKJ	L 	L 	L *1diot{+/:7 7.q$)/BBaKKK	
 
 

 \)
XNNN%<<czH
r8   c                    t          j                    }| j        |_        t	          j        | j                  |_        | j        |_        d|_        t          | d          r| j
        |_        |                    |           dS )a  Export the density grid to an MRC/CCP4 file.
        
        The MRC2014 file format is used via the mrcfile library.
        
        Parameters
        ----------
        filename : str
            Output filename
        **kwargs
            Additional keyword arguments (currently ignored)
        
        Notes
        -----
        * Only orthorhombic unit cells are supported
        * If the Grid was loaded from an MRC file, the original header
          information (including axis ordering) is preserved
        * For new grids, standard ordering (mapc=1, mapr=2, maps=3) is used
        
        .. versionadded:: 1.1.0
        r   r   N)r   r   r   rU   rJ   diagr2   r1   rankhasattrr   r   r   )r/   r4   r   mrc_files       r   r   zGrid._export_mrc  ss    , 799DJ//+ 4'' 	/".HO 	x     r8   c                 4    |                      |d           dS )a  Save a grid object to `filename` and add ".pickle" extension.

        Internally, this calls
        ``Grid.export(filename, format="python")``. A grid can be
        regenerated from the saved data with ::

           g = Grid(filename="grid.pickle")

        .. note::
           The pickle format depends on the Python version and
           therefore it is not guaranteed that a grid saved with, say,
           Python 2.7 can also be read with Python 3.5. The OpenDX format
           is a better alternative for portability.

        r   r   N)r   )r/   r4   s     r   savez	Grid.save  s       	H(33333r8   c              #      K   t          j        | j        j                  D ](}| j        t          j        |          z  | j        z   V  )dS )zReturns the coordinates of the centers of all grid cells as an iterator.


        See Also
        --------
        :func:`numpy.ndindex`
        N)rJ   ndindexr   r   r2   rU   r1   )r/   idxs     r   centerszGrid.centers  sV       =11 	> 	>C*u{3///$+=====	> 	>r8   c                 8   t          |t                    r2t          d t          |j        | j                  D                       }nA	 t          j        | j        |          j        | j        j        k    }n# t          $ r d}Y nw xY w|st          d          dS )a  Check if `other` can be used in an arithmetic operation.

        `other` is compatible if

        1) `other` is a scalar or an array-like broadcastable to the grid
        2) `other` is a grid defined on the same edges

        In order to make `other` compatible, resample it on the same
        grid as this one using :meth:`resample`.

        Parameters
        ----------
        other : Grid or float or int
           Another object to be used for standard arithmetic
           operations with this :class:`Grid`

        Raises
        ------
        TypeError
              if not compatible

        See Also
        --------
        :meth:`resample`
        c              3   F   K   | ]\  }}t          j        ||          V  d S N)rJ   allcloserM   
other_edge	self_edges      r   	<genexpr>z(Grid.check_compatible.<locals>.<genexpr>  sF          )J	 z955           r8   FzThe argument cannot be arithmetically combined with the grid. It must be broadcastable to the grid's shape or a `Grid` with identical edges. Use `Grid.resample(other.edges)` to make a new grid that is compatible with `other`.T)r(   r   allr\   r0   rJ   	broadcastr   r   rT   r   )r/   otheris_compatibles      r   check_compatiblezGrid.check_compatible  s    4 eT"" 		&    -0dj-I-I       MM
& %	5 A A G49? Z & & & %& 	,+, , ,
 ts   	-A7 7BBc                 8  	
 ddl 	|| j        }| j        | j        }|                                	 |                              }n# t          $ r |}Y nw xY w	j                            ||          | j	        
| j
        d 	
fd}|S )a0  Returns a function F(x,y,z) that interpolates any values on the grid.

        _interpolationFunctionFactory(self,spline_order=3,cval=None) --> F

        *cval* is set to :meth:`Grid.grid.min`. *cval* cannot be chosen too
        large or too small or NaN because otherwise the spline interpolation
        breaks down near that region and produces wild oscillations.

        .. Note:: Only correct for equally spaced values (i.e. regular edges with
                  constant delta).
        .. SeeAlso:: http://www.scipy.org/Cookbook/Interpolation
        r   N)orderc                 6    t          j        |           |z
  |z  S r   )rJ   
atleast_1d)cnewc0dcs      r   
_transformz6Grid._interpolationFunctionFactory.<locals>._transformQ  s    $T**R/255r8   c                       t          j         fdt          t                               D                       }j                            |dd          S )aG  B-spline function over the data grid(x,y,z).

            interpolatedF([x1,x2,...],[y1,y2,...],[z1,z2,...]) -> F[x1,y1,z1],F[x2,y2,z2],...

            Example usage for resampling::
              >>> XX,YY,ZZ = numpy.mgrid[40:75:0.5, 96:150:0.5, 20:50:0.5]
              >>> FF = _interpolationFunction(XX,YY,ZZ)
            c                 N    g | ]!} |         |         |                   "S rj   rj   )rM   ir   rA   r   x0s     r   rQ   zMGrid._interpolationFunctionFactory.<locals>.interpolatedF.<locals>.<listcomp>^  s?     # # #aKNBqE2a599 # # #r8   Fconstant)	prefiltermodecval)rJ   rU   rangere   ndimagemap_coordinates)rA   _coordinatesr   coeffsr   r   scipyr   s   ` r   interpolatedFz9Grid._interpolationFunctionFactory.<locals>.interpolatedFT  s     !;# # # # # # #5J! J! D" D" # # #$ $L =001=;@6@6:	 1 < < <r8   )scipy.ndimager3   r'   r   r{   filledr	   r   spline_filterr1   r2   )r/   spline_orderr   r   _datar   r   r   r   r   r   s     `   @@@@@r   rn   z"Grid._interpolationFunctionFactory+  s      	  :L<*Dy<88::D	KK%%EE 	 	 	EEE	 ,,U,,GG[Z	6 	6 	6	< 	< 	< 	< 	< 	< 	< 	< 	< 	<" s   A A A c                 $   t          |t                    sdS t          j        |j        | j        k              oWt          j        |j        | j        k              o5t          j        d t          |j        | j                  D                       S )NFc              3   L   K   | ]\  }}t          j        ||k              V   d S r   )rJ   r   r   s      r   r   zGrid.__eq__.<locals>.<genexpr>l  sQ       7 7.Z Ii') )7 7 7 7 7 7r8   )r(   r   rJ   r   r   r1   r\   r0   r/   r   s     r   __eq__zGrid.__eq__g  s    %&& 	5yJ$)#% % ).LDK'*) *)-2Y 7 7 
 7 7 7 . .	r8   c                 .    |                      |           S r   )r  r  s     r   __ne__zGrid.__ne__s  s    ;;u%%%%r8   c                     |                      |           |                     | j        t          |          z   | j                  S ry   r   r?   r   r   r0   r  s     r   __add__zGrid.__add__v  ;    e$$$~~di%,,6dj~IIIr8   c                     |                      |           |                     | j        t          |          z
  | j                  S ry   r  r  s     r   __sub__zGrid.__sub__z  r  r8   c                     |                      |           |                     | j        t          |          z  | j                  S ry   r  r  s     r   __mul__zGrid.__mul__~  r  r8   c                     |                      |           |                     | j        t          |          z  | j                  S ry   r  r  s     r   __truediv__zGrid.__truediv__  r  r8   c                     |                      |           |                     | j        t          |          z  | j                  S ry   r  r  s     r   __floordiv__zGrid.__floordiv__  s;    e$$$~~di5<<7tz~JJJr8   c                     |                      |           |                     t          j        | j        t          |                    | j                  S ry   )r   r?   rJ   powerr   r   r0   r  s     r   __pow__zGrid.__pow__  sU    e$$$~~K	e  *	    	r8   c                     |                      |           |                     t          |          | j        z   | j                  S ry   r   r?   r   r   r0   r  s     r   __radd__zGrid.__radd__  ;    e$$$~~eEllTY6dj~IIIr8   c                     |                      |           |                     t          |          | j        z
  | j                  S ry   r  r  s     r   __rsub__zGrid.__rsub__  r  r8   c                     |                      |           |                     t          |          | j        z  | j                  S ry   r  r  s     r   __rmul__zGrid.__rmul__  r  r8   c                     |                      |           |                     t          |          | j        z  | j                  S ry   r  r  s     r   __rtruediv__zGrid.__rtruediv__  r  r8   c                     |                      |           |                     t          |          | j        z  | j                  S ry   r  r  s     r   __rfloordiv__zGrid.__rfloordiv__  s;    e$$$~~eElldi7tz~JJJr8   c                     |                      |           |                     t          j        t	          |          | j                  | j                  S ry   )r   r?   rJ   r  r   r   r0   r  s     r   __rpow__zGrid.__rpow__  sU    e$$$~~Ke	  *	    	r8   c                 x    	 | j         j        }n# t          $ r d}Y nw xY wd                    | j        |          S )Nnoz<{0} with {1!r} bins>)r   r   r	   r   r?   )r/   binss     r   __repr__zGrid.__repr__  sN    	9?DD 	 	 	DDD	&--dndCCCs    )NNNNNr   NFr   )NT)NNNNN)NF)F)NNr   )Nr   )NN)2__name__
__module____qualname____doc__r   r5   propertyr3   setterrC   rb   r:   r>   rt   r<   rX   rW   rV   r   r   r   r.   r-   r"   r   r    r!   r   r   r   r   r   r   r   rn   r  r
  r  r  r  r  r  r  r  r  r!  r#  r%  r'  r+  rj   r8   r   r   r   :   s       X Xv NAE;<5:/A /A /A /Ab 1 1 X1  &	 	 '&	.. .. ..`2$ 2$ 2$hG G G, 1# 1# X1#f( ( ( (
N N N N1 1 1 17 7 7 77 7 7 7   (@ @ @ @
? ? ? ? '1 '1 '1 '1T> > > >/ / /1 1 1 1C C CC C C.; .; .; .;h: : :& & & &P!! !! !!F4 4 4$	> 	> 	>* * *X: : : :x
 
 
& & &J J JJ J JJ J JJ J JK K K  J J JJ J JJ J JJ J JK K K  D D D D Dr8   r   c                     t          |           } t          t          t          |                     }t          |           }d}|D ]}||z  }g }t	          |           D ]\  }}dg|z  }||         ||<   t          j        |                              |          }	t	          |          D ]"\  }
}|
|k    r|	                    ||
          }	#|	                    |	           t          |          S )a  Return a mesh grid for N dimensions.

    The input are N arrays, each of which contains the values along one axis of
    the coordinate system. The arrays do not have to have the same number of
    entries. The function returns arrays that can be fed into numpy functions
    so that they produce values for *all* points spanned by the axes *arrs*.

    Original from
    http://stackoverflow.com/questions/1827489/numpy-meshgrid-in-3d and fixed.

    .. SeeAlso: :func:`numpy.meshgrid` for the 2D case.
    r   )axis)
tuplerl   rm   re   r   rJ   r   reshaperepeatr   )arrslensr   szsansr   arrslcarr2js              r   r=   r=     s     ;;DCD
d))C	
B  
a
CD//  3cCiaA$$,,S11t__ 	/ 	/EArAvv{{2A{..

4::r8   )r/  r   r   r   rJ    r   r   r   r   objectr   r=   rj   r8   r   <module>rB     s    @ 
			   
                    yD yD yD yD yD6 yD yD yDx         r8   