File: coordinatebounds.py

package info (click to toggle)
cf-python 1.3.2%2Bdfsg1-4
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 7,996 kB
  • sloc: python: 51,733; ansic: 2,736; makefile: 78; sh: 2
file content (141 lines) | stat: -rw-r--r-- 3,939 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
from .variable import Variable


# ====================================================================
#
# CoordinateBounds object
#
# ====================================================================

class CoordinateBounds(Variable):
    '''
    
A CF coordinate's bounds object containing cell boundaries or
intervals of climatological time. The parent coordinate's
`!climatology` attribute indicates which type of bounds are present.

'''
    # ----------------------------------------------------------------
    # Attribute (read only)
    # ----------------------------------------------------------------
    @property
    def lower_bounds(self):
        '''

The lower coordinate bounds in a `cf.Data` object.

``b.lower_bounds`` is equivalent to ``b.data.min(axes=-1)``.

.. seealso:: `upper_bounds`

:Examples:

>>> print b.array
[[ 5  3]
 [ 3  1]
 [ 1 -1]]
>>> b.lower_bounds
<CF Data: [3, ..., -1]>
>>> print b.lower_bounds.array
[ 3  1 -1]

'''
        if not self._hasData:
            raise ValueError("Can't get lower bounds when there are no bounds")

        return self.data.min(-1).squeeze(-1, i=True)
    #--- End: def

    # ----------------------------------------------------------------
    # Attribute (read only)
    # ----------------------------------------------------------------
    @property
    def upper_bounds(self):
        '''

The upper coordinate bounds in a `cf.Data` object.

``b.upper_bounds`` is equivalent to ``b.data.max(axes=-1)``.

.. seealso:: `lower_bounds`

:Examples:

>>> print b.array
[[ 5  3]
 [ 3  1]
 [ 1 -1]]
>>> b.upper_bounds      
<CF Data: [5, ..., 1]>
>>> b.upper_bounds.array     
array([5, 3, 1])

'''
        if not self._hasData:
            raise ValueError("Can't get upper bounds when there are no bounds")

        return self.data.max(-1).squeeze(-1, i=True)
    #--- End: def

    def contiguous(self, overlap=True, direction=None):
        '''
      
Return True if the bounds are contiguous.

Bounds are contiguous if the cell boundaries match up, or
overlap, with the boundaries of adjacent cells.

In general, it is only possible for 1 or 0 dimensional coordinates
with bounds to be contiguous, but size 1 coordinates with any number
of dimensions are always contiguous.

An exception occurs if the coordinate is multdimensional and has more
than one element.

'''
        if not self._hasData:
            return False    

        nbounds = self.shape[-1]

        if self.size == nbounds:
            return True

        if nbounds == 4 and self.ndim ==3:
            if overlap == True:
                raise ValueError("Cannot tell if 2D coordinate bounds are" +
                                 " contiguous if overlap is True.")
            bnd = self.array
            for j in xrange(self.shape[0] - 1):
                for i in xrange(self.shape[1] - 1):
                    # check cells (j, i) and cells (j, i+1) are contiguous
                    if bnd[j,i,1] != bnd[j,i+1,0] or \
                       bnd[j,i,2] != bnd[j,i+1,3]:
                        return False
                    # check cells (j, i) and (j+1, i) are contiguous
                    if bnd[j,i,3] != bnd[j+1,i,0] or \
                       bnd[j,i,2] != bnd[j+1,i,1]:
                        return False
            return True

        if  nbounds > 2 or self.ndim > 2:
            raise ValueError(
"Can't tell if a multidimensional coordinate bounds are contiguous")

        data = self.Data
        
        if not overlap: 
            return data[1:, 0].equals(data[:-1, 1])
        else:
            if direction is None:
                b = data[(0,)*(data.ndim-1)].array
                direction =  b.item(0,) < b.item(1,)
            #--- End: if
        
            if direction:
                return (data[1:, 0] <= data[:-1, 1]).all()
            else:
                return (data[1:, 0] >= data[:-1, 1]).all()
    #--- End: def

#--- End: class