def __init__(self, varname, clim, segmentlist, name=None, unit=None): """Transect constructor. Args: - *varname*: the name of the variable to extract. - *clim*: a list or tuple with the two limit values (minimum and maximum). - *segmentlist*: a list Segment objects. Can be an empty list. - *name* (optional): a string defining the transect's name. If set to None it will be set to varname (default: None). - *unit* (optional): a string defining the transect's measurement unit (default: None). """ if varname is None: raise ValueError("varname cannot be None") self.__varname = str(varname) if name is None: self.__name = self.__varname else: self.__name = str(name) if unit is None: self.__unit = None else: self.__unit = str(unit) if not isinstance(clim, (list, tuple)) or (len(clim) != 2) or not (is_number(clim[0]) and is_number(clim[1])): raise ValueError("clim must be a list of two numbers") self.__clim = clim if not isinstance(segmentlist, (list, tuple)) or ((len(segmentlist) > 0) and not isinstance(segmentlist[0], (Segment,))): raise ValueError("segmentlist must be a list of Segments") self.__segmentlist = segmentlist #Variable data cache self.__datacache = { 'filename':None, 'data':None } self.__mask = None
def __get_segment_data(self, segment_index): #Input validation if not is_number(segment_index): raise ValueError("'%s' is not a number." % (segment_index,)) seg = self.__segmentlist[segment_index] #Retrieve indices x_min, y_min = self.__mask.convert_lon_lat_to_indices(seg.lon_min, seg.lat_min) x_max, y_max = self.__mask.convert_lon_lat_to_indices(seg.lon_max, seg.lat_max) #Check for single point case if (x_min == x_max) and (y_min == y_max): raise ValueError("Invalid segment: %s" % (seg,)) #Get the output data if x_min == x_max: data = np.array(self.__datacache['data'][:, y_min:y_max, x_min], dtype=float) h_vals = self.__mask.ylevels[y_min:y_max,x_min] elif y_min == y_max: data = np.array(self.__datacache['data'][:, y_min, x_min:x_max], dtype=float) h_vals = self.__mask.xlevels[y_min,x_min:x_max] else: #Divide the segment in points xs = np.linspace(x_min,x_max,num=seg.points) ys = np.linspace(y_min,y_max,num=seg.points) xs = np.round(xs) ys = np.round(ys) #Fill data with the nearest neighbour data = list() for i in range(seg.points): data.append(self.__datacache['data'][:,ys[i],xs[i]]) #Convert data to a Numpy array data = np.array(data) data = data.transpose() #TODO: find a meaningful array for h_vals. h_vals = np.array(range(seg.points)) z_vals = self.__mask.zlevels return data, h_vals, z_vals
def __init__(self, varname, longvarname, units, layerlist, clim): #Input validation self.__varname = str(varname) self.__longvarname = str(longvarname) self.__units = units if not isinstance(layerlist, (list, tuple)) or ((len(layerlist) > 0) and not isinstance(layerlist[0], (Layer,))): raise ValueError("layerlist must be a list of Layers") self.__layerlist = layerlist if not (clim is None): if not isinstance(clim, (list, tuple)) or (len(clim) != 2) or not (is_number(clim[0]) and is_number(clim[1])): raise ValueError("clim must be a list of two numbers") self.__clim = clim self.__climslist = list()
def __init__(self, lon_lat_min, lon_lat_max, name=None, points=50): """Segment constructor. Args: - *lon_lat_min*: tuple or list with Segment's starting point in longitude and latitude. - *lon_lat_max*: tuple or list with Segment's ending point in longitude and latitude. - *name* (optional): a string defining the name of the segment (default: None). - *points* (optional): the number of points of the segment (default: 50). It is a required argument for diagonals and it is ignored for fixed latitude and fixed longitude segments. """ if name is None: self.__name = None else: self.__name = str(name) if not (isinstance(lon_lat_min, (list, tuple)) and isinstance(lon_lat_max, (list, tuple))): raise ValueError("lon_lat_min and lon_lat_max must be tuples or lists") if not ((len(lon_lat_min) == 2) and (len(lon_lat_max) == 2)): raise ValueError("lon_lat_min and lon_lat_max must hold two values") for t in [lon_lat_min, lon_lat_max]: for el in t: if not is_number(el): raise ValueError("%s is not a number" % (el,)) self.__lon_min = lon_lat_min[0] self.__lat_min = lon_lat_min[1] self.__lon_max = lon_lat_max[0] self.__lat_max = lon_lat_max[1] self.points = None #If the segment is diagonal check that points is a number greater than 0 if (self.__lon_min != self.__lon_max) and (self.__lat_min != self.__lat_max): if not is_number(points) or (points <= 0): raise ValueError("points must be defined as a number greater than zero") else: self.points = points
def from_square_cutting(mask, degrees, start_lon, start_lat): """ Creates a list of SubMask objects from cutting a Mask object into square sections. The cutting starts from a point and proceeds to cut along longitude then along latitude. ++++++++ ++++++++ s->+++++ ++++++++ -> s->+++++ -> ssssssss s->+++++ ssssssss ssssssss Args: - *mask*: a Mask object. - *degrees*: number of degrees for a sigle section side. - *start_lon*: starting longitude point. - *start_lat*: starting latitude point. Returns: a list of SubMasks mapping a single section each. """ # Input validation if not isinstance(mask, Mask): raise ValueError("mask must be an instance of Mask") if not is_number(degrees): raise ValueError("degrees must be a number") if not is_number(start_lon): raise ValueError("start_lon must be a number") if not is_number(start_lat): raise ValueError("start_lat must be a number") # Get mask dimensions min_lon = mask.xlevels.min() max_lon = mask.xlevels.max() min_lat = mask.ylevels.min() max_lat = mask.ylevels.max() # Compute maximum value for degrees max_deg = min([(max_lon - min_lon), (max_lat - min_lat)]) if degrees <= 0: raise ValueError("degrees must be greater than 0.") if degrees > max_deg: raise ValueError("The degrees value of %g is too big for this mask (maximum: %g)" % (degrees, max_deg)) # Check if starting point is inside the original mask if (start_lon > max_lon) or (start_lon < min_lon): raise ValueError("Invalid longitude %g (min: %g, max: %g)" % (start_lon, min_lon, max_lon)) if (start_lat > max_lat) or (start_lat < min_lat): raise ValueError("Invalid latitude %g (min: %g, max: %g)" % (start_lat, min_lat, max_lat)) output = list() # Bottom Left point BL_point = [start_lon, start_lat] # Top Right point TR_point = [start_lon + degrees, start_lat + degrees] # Section indices lon_in = 0 lat_in = 0 # Latitude cycle while (TR_point[1] <= max_lat): # Longitude cycle while (TR_point[0] <= max_lon): # Create the Rectagle rect = Rectangle(BL_point[0], TR_point[0], BL_point[1], TR_point[1]) # Create the basin basin = SimpleBasin("section_%d_%d" % (lat_in, lon_in), rect) # Create the SubMask and append it to output output.append(SubMask(basin, maskobject=mask)) # Increment longitude index lon_in += 1 # Increment longitude BL_point[0] += degrees TR_point[0] += degrees # Increment latitude index lat_in += 1 # Increment latitude BL_point[1] += degrees TR_point[1] += degrees # Reset Longitude index lon_in = 0 # Reset Longitude BL_point[0] = start_lon TR_point[0] = start_lon + degrees return output