def RequestInformation(): sys.path.insert(0, r'EMC_SRC_PATH') import IrisEMC_Paraview_Lib as lib from paraview import util from os.path import splitext import IrisEMC_Paraview_Utils as utils import IrisEMC_Paraview_Param as param depth_begin = float(Depth_begin) depth_end = float(Depth_end) File_name = File_name.strip() ext = None if File_name in list(param.filesDict.values()) or not ( File_name.lower().endswith(param.filesExtDict['ssl'].lower()) or File_name.lower().endswith(param.filesExtDict['geo'].lower())): if utils.support_nc(): ext = param.filesExtDict['ssl'] else: ext = param.filesExtDict['geo'] fileFound, address, source = lib.find_file(File_name, loc=r'EMC_MODELS_PATH', ext=ext) if not fileFound: raise Exception('model file "' + address + '" not found! Aborting.') Latitude_begin, Latitude_end, Longitude_begin, Longitude_end = lib.get_area( Area, Latitude_begin, Latitude_end, Longitude_begin, Longitude_end) this_filename, extension = splitext(address) if extension.lower() == '.nc': nx, ny, nz = lib.read_netcdf_model(address, Latitude_variable, Longitude_variable, Depth_variable, (Latitude_begin, Longitude_begin), (Latitude_end, Longitude_end), depth_begin, depth_end, Vertical_Scaling, inc=Sampling, extent=True) else: try: nx, ny, nz = lib.read_geocsv_model_3d( address, (Latitude_begin, Longitude_begin), (Latitude_end, Longitude_end), depth_begin, depth_end, Vertical_Scaling, inc=Sampling, extent=True) except Exception: raise Exception('cannot recognize model file "' + address + '"! Aborting.') # ABSOLUTELY NECESSARY FOR THE READER TO WORK: util.SetOutputWholeExtent(self, [0, nx, 0, ny, 0, nz])
def get_points_in_area(lat, lon, dep, ll, ur, inc): """find points that fall with in an area Keyword arguments: lat: latitude list to check lon: longitude list to check dep: depth to use ll: lower-left coordinate ur: upper-right coordinate Return values: latitude: list of latitudes that are in the area longitude: list of longitude that are in the area depth: list of depths that are in the volume """ use_dep = dep if type(dep) is list: use_dep = [dep[0]] latitude = [] longitude = [] depth = [] last_i = -1 for i, lon_val in enumerate(lon): if i != 0 and i != len(lon) - 1 and i != last_i + inc: continue last_i = i for j, depth_val in enumerate(use_dep): last_k = -1 for k, lat_val in enumerate(lat): if k != 0 and k != len(lat) - 1 and k != last_k + inc: continue last_k = k if utils.isValueIn(lat_val, ll[0], ur[0]) and utils.isLongitudeIn( lon_val, ll[1], ur[1]): if lon_val not in longitude: longitude.append(lon_val) if depth_val not in depth: depth.append(depth_val) if lat_val not in latitude: latitude.append(lat_val) return latitude, longitude, depth
def RequestInformation(): from os.path import splitext sys.path.insert(0, r'EMC_SRC_PATH') import IrisEMC_Paraview_Lib as lib from paraview import util import IrisEMC_Paraview_Utils as utils import IrisEMC_Paraview_Param as param Latitude_Begin, Latitude_End, Longitude_Begin, Longitude_End = lib.get_area( Area, Latitude_Begin, Latitude_End, Longitude_Begin, Longitude_End) if len(Alternate_FileName.strip()) > 0: FileName = Alternate_FileName.strip() Label = ' '.join(['SLAB', lib.file_name(Alternate_FileName).strip()]) else: FileName = lib.usgsSlabKeys[Slab] Label = ' '.join(['USGS Slab 1.0 -', lib.usgsSlabValues[Slab].strip()]) FileName = FileName.strip() ext = None if FileName in list(param.usgsSlabDict.keys()): if utils.support_nc(): ext = param.usgsSlabExtDict['ssl'] else: ext = param.usgsSlabExtDict['geo'] fileFound, address, source = lib.find_file(FileName, loc=r'EMC_SLABS_PATH', ext=ext) if not fileFound: raise Exception('model file "' + address + '" not found! Aborting.') this_filename, extension = splitext(address) if extension.lower() == '.grd': nx, ny, nz = lib.read_slab_file(address, (Latitude_Begin, Longitude_Begin), (Latitude_End, Longitude_End), inc=Sampling, extent=True) elif extension.lower() == '.csv': nx, ny, nz = lib.read_geocsv_model_2d( address, (Latitude_Begin, Longitude_Begin), (Latitude_End, Longitude_End), Sampling, 0, extent=True) else: raise Exception('cannot recognize model file "' + address + '"! Aborting.') # ABSOLUTELY NECESSARY FOR THE READER TO WORK: util.SetOutputWholeExtent(self, [0, nx, 0, ny, 0, nz])
def get_points_in_volume(lat, lon, dep, ll, ur, inc, depth_min, depth_max): """find points that fall with in a volume Keyword arguments: lat: latitude list to check lon: longitude list to check dep: depth list to check ll: lower-left coordinate ur: upper-right coordinate depth_min: minimum depth of volume depth_max: maximum depth of volume Return values: latitude: list of latitudes that are in the volume longitude: list of longitude that are in the volume depth: list of depths that are in the volume """ latitude = [] longitude = [] depth = [] last_i = -1 for i, lon_val in enumerate(lon): if i != 0 and i != len(lon) - 1 and i != last_i + inc: continue last_i = i for j, depth_val in enumerate(dep): last_k = -1 for k, lat_val in enumerate(lat): if k != 0 and k != len(lat) - 1 and k != last_k + inc: continue last_k = k if utils.isValueIn(lat_val, ll[0], ur[0]) and utils.isLongitudeIn(lon_val, ll[1], ur[1]) and \ utils.isValueIn(float(depth_val), depth_min, depth_max): if lon_val not in longitude: longitude.append(lon_val) if depth_val not in depth: depth.append(depth_val) if lat_val not in latitude: latitude.append(lat_val) return latitude, longitude, depth
def RequestInformation(): sys.path.insert(0, r'EMC_SRC_PATH') from os.path import splitext import IrisEMC_Paraview_Lib as lib from paraview import util import IrisEMC_Paraview_Utils as utils import IrisEMC_Paraview_Param as param if len(Alternate_FileName.strip()) > 0: file_name = Alternate_FileName.strip() else: file_name = lib.topoKeys[TopoFile] file_name = file_name.strip() ext = None if file_name in list(param.topoDict.keys()): if utils.support_nc(): ext = param.topoExtDict['ssl'] else: ext = param.topoExtDict['geo'] fileFound, address, source = lib.find_file(file_name, loc=r'EMC_MODELS_PATH', ext=ext) Latitude_Begin, Latitude_End, Longitude_Begin, Longitude_End = lib.get_area( Area, Latitude_Begin, Latitude_End, Longitude_Begin, Longitude_End) this_filename, extension = splitext(address) if extension.lower() in ['.nc', '.grd']: nx, ny, nz = lib.read_netcdf_topo_file( address, (Latitude_Begin, Longitude_Begin), (Latitude_End, Longitude_End), Sampling, Roughness, lon_var=Longitude_Variable, lat_var=Latitude_Variable, elev_var=Elevation_Variable, extent=True) else: try: nx, ny, nz = lib.read_geocsv_model_2d( address, (Latitude_Begin, Longitude_Begin), (Latitude_End, Longitude_End), Sampling, Roughness, extent=True) except Exception: raise Exception('cannot recognize model file "' + address + '"! Aborting.') # ABSOLUTELY NECESSARY FOR THE READER TO WORK: util.SetOutputWholeExtent(self, [0, nx, 0, ny, 0, nz])
def xyz2llz(x, y, z): """convert earth-centered, earth-fixed (ECEF) cartesian x, y, z to latitude, longitude, and altitude code is based on: https://www.mathworks.com/matlabcentral/fileexchange/7941-convert-cartesian--ecef--coordinates-to-lat--lon--alt? focused=5062924&tab=function Keyword arguments: x: x-coordinate normalized to the radius of Earh y: y-coordinate normalized to the radius of Earh z: z-coordinate normalized to the radius of Earh Return values: lat: latitude (deg) lon: longitude (deg) depth: depth (km) """ # World Geodetic System 1984, WGS 84 erad = np.float64( 6378137.0) # Radius of the Earth in meters (equatorial radius, WGS84) rad = 1 # sphere radius e = np.float64(8.1819190842622e-2) # convert to radius x = x * erad / rad y = y * erad / rad z = z * erad / rad b = np.sqrt(erad * erad * (1 - e * e)) ep = np.sqrt((erad * erad - b * b) / (b * b)) p = np.sqrt(x * x + y * y) th = np.arctan2(erad * z, b * p) lon = np.arctan2(y, x) lat = np.arctan2((z + ep * ep * b * np.sin(th) * np.sin(th) * np.sin(th)), (p - e * e * erad * np.cos(th) * np.cos(th) * np.cos(th))) N = erad / np.sqrt(1.0 - e * e * np.sin(lat) * np.sin(lat)) alt = p / np.cos(lat) - N lon = np.mod(lon, (math.pi * 2.0)) lon = np.rad2deg(lon) lon = utils.lon_180(lon) lat = np.rad2deg(lat) alt = -1 * alt / 1000.0 # depth as negative alt return lat, lon, alt
def read_netcdf_model(model_file, lat_variable, lon_variable, depth_variable, ll, ur, depth_min, depth_max, roughness, inc, extent=False): """read in an EMC Earth model in the netCDF format Keyword arguments: model_file: model file ll: lower-left coordinate ur: upper-right coordinate depth_min: minimum depth depth_max: maximum depth inc: grid sampling interval Return values: x: x-coordinate normalized to the radius of the Earth y: y-coordinate normalized to the radius of the Earth z: z-coordinate normalized to the radius of the Earth meta: file metadata information """ # ParaView on some platforms does not have SciPy module if not utils.support_nc(): print( "[ERR] Cannot read netCDF files on this platform, try GeoCSV format!" ) return [], [], [], [], {} # NetCDF files, when opened read-only, return arrays that refer directly to memory-mapped data on disk: print(f"[INFO] Reading model file {model_file}") data = netcdf.netcdf_file(model_file, 'r') variables = [] for name in list(data.variables.keys()): if name not in (depth_variable, lon_variable, lat_variable): variables.append(name) # expects variables be a function of latitude, longitude and depth, find the order var = variables[0] for i, value in enumerate(data.variables[var].dimensions): if value == depth_variable: depth_index = i elif value == lon_variable: lon_index = i else: lat_index = i lat = data.variables[lat_variable][:].copy() lon = data.variables[lon_variable][:].copy() lon, lon_map = utils.lon_180(lon, fix_gap=True) depth = data.variables[depth_variable][:].copy() # select the values within the ranges (this is to get a count only) latitude, longitude, depth2 = get_points_in_volume(lat, lon, depth, ll, ur, inc, depth_min, depth_max) # model data grid definition V = {} nx = len(longitude) ny = len(depth2) nz = len(latitude) if extent: return nx - 1, ny - 1, nz - 1 index = [-1, -1, -1] meta = { 'depth': [], 'lat': [100, -100], 'lon': [400, -400], 'source': model_file } missing_value = None if hasattr(data.variables[var], 'missing_value'): missing_value = float(data.variables[var].missing_value) for l, var_val in enumerate(variables): X = np.zeros((nx, ny, nz)) Y = np.zeros((nx, ny, nz)) Z = np.zeros((nx, ny, nz)) v = np.zeros((nx, ny, nz)) data_in = data.variables[var_val][:].copy() # increment longitudes, we want to keep the first and last longitude regardless of inc for i, lon_val in enumerate(lon): for j, depth_val in enumerate(depth): for k, lat_val in enumerate(lat): if lon_val in longitude and lat_val in latitude and depth_val in depth2: meta['lon'] = [ min(meta['lon'][0], lon_val), max(meta['lon'][0], lon_val) ] meta['lat'] = [ min(meta['lat'][0], lat_val), max(meta['lat'][0], lat_val) ] if depth_val not in meta['depth']: meta['depth'].append(depth_val) x, y, z = llz2xyz(lat_val, lon_val, depth_val * roughness) ii = longitude.index(lon_val) jj = depth2.index(depth_val) kk = latitude.index(lat_val) X[ii, jj, kk] = x Y[ii, jj, kk] = y Z[ii, jj, kk] = z index[depth_index] = j index[lat_index] = k index[lon_index] = i this_value = data_in[index[0]][index[1]][index[2]] if this_value is None: v[ii, jj, kk] = None elif this_value is not None: if this_value == missing_value: v[ii, jj, kk] = None this_value = None else: v[ii, jj, kk] = this_value else: v[ii, jj, kk] = this_value V[var_val] = v data.close() return X, Y, Z, V, meta
2019-01-30 Manoch: v.2019.030 event service call request order changed from magnitude to time-asc 2019-01-22 Manoch: v.2019.022 added animation directory under earthquakes path and introduced time_column for use with earthquake 2019-01-14 Manoch: v.2019.014 support for getting the default volcano data from IRIS EMC file repository 2018-11-12 Manoch: v.2018.316 added Platform check to load .csv files instead of .nc for Windows 2018-10-17 Manoch: v.2018.290 updates for R1 2018-09-13 Manoch: v.2018.256 added support for EMC_DEFAULT_GSV_MODEL 2018-05-09 Manoch: v.2018.129 added EMC_DEFAULT_2DMODEL tp fileDict 2018-04-27 Manoch: v.2018.117 updateid irisEMC_Files_URL 2018-04-23 Manoch: v.2018.113 updateid lat and lon limits for the world added very low resolution coastline data file 2018-03-21 Manoch: v.2018.080 release """ # see if SSL is available for HTTPS requests ssl_available = utils.do_https() HTTP_PROTOCOL = 'https:' if not ssl_available: HTTP_PROTOCOL = 'http:' def sort_dict_by_value(dictionary): """Splits a Python dictionary to two lists containing keys and values sorted by values. Keyword arguments: thisDict: a Python dictionary Return values: keys: list of keys in the dictionary values: list of values in the dictionary """
def RequestData(): # V.2019.030 import sys sys.path.insert(0, r'EMC_SRC_PATH') from paraview.simple import RenameSource, GetActiveViewOrCreate, ColorBy, GetDisplayProperties, GetActiveSource import numpy as np import csv import os from os.path import splitext from vtk.util import numpy_support as nps import IrisEMC_Paraview_Lib as lib import IrisEMC_Paraview_Utils as utils import IrisEMC_Paraview_Param as param # elevation units in meters Roughness = -1 * float(Roughness) baseline = float(Depth_Bias) if len(Alternate_FileName.strip()) > 0: file_name = Alternate_FileName.strip() label = ' '.join(['Topo', lib.file_name(Alternate_FileName).strip()]) else: file_name = lib.topoKeys[TopoFile] label = lib.topoValues[TopoFile] file_name = file_name.strip() ext = None if file_name in list(param.topoDict.keys()): if utils.support_nc(): ext = param.topoExtDict['ssl'] else: ext = param.topoExtDict['geo'] # make sure we have input files file_found, address, source = lib.find_file(file_name, loc=r'EMC_MODELS_PATH', ext=ext) if not file_found: raise Exception('Topo file "' + address + '" not found! Aborting.') this_filename, extension = splitext(address) sg = self.GetOutput() # vtkPolyData Latitude_Begin, Latitude_End, Longitude_Begin, Longitude_End = lib.get_area( Area, Latitude_Begin, Latitude_End, Longitude_Begin, Longitude_End) label2 = " - %s (%0.1f,%0.1f,%0.1f,%0.1f)" % ( lib.areaValues[Area], Latitude_Begin, Latitude_End, Longitude_Begin, Longitude_End) if extension.lower() in ['.nc', '.grd']: X, Y, Z, V, label = lib.read_netcdf_topo_file( address, (Latitude_Begin, Longitude_Begin), (Latitude_End, Longitude_End), Sampling, Roughness, base=baseline, lon_var=Longitude_Variable, lat_var=Latitude_Variable, elev_var=Elevation_Variable, unit_factor=float(Unit_Factor), extent=False) else: try: X, Y, Z, V, meta = lib.read_geocsv_model_2d( address, (Latitude_Begin, Longitude_Begin), (Latitude_End, Longitude_End), Sampling, Roughness, base=baseline, unit_factor=float(Unit_Factor), extent=False) except Exception: raise Exception('cannot recognize model file "' + address + '"! Aborting.') nx = len(X) ny = len(X[0]) nz = len(X[0][0]) sg.SetDimensions(nx, ny, nz) # # make geometry # points = vtk.vtkPoints() for k in range(nz): for j in range(ny): for i in range(nx): points.InsertNextPoint((X[i, j, k], Y[i, j, k], Z[i, j, k])) sg.SetPoints(points) # # make geometry # count = 0 for var in list(V.keys()): scalars = vtk.vtkFloatArray() scalars.SetNumberOfComponents(1) scalars.SetName(var) for k in range(nz): for j in range(ny): for i in range(nx): scalars.InsertNextValue(V[var][i, j, k]) if count == 0: sg.GetPointData().SetScalars(scalars) else: sg.GetPointData().AddArray(scalars) count += 1 # store metadata fieldData = sg.GetFieldData() fieldData.AllocateArrays(3) # number of fields data = vtk.vtkFloatArray() data.SetName('Latitude\nRange (deg)') data.InsertNextValue(Latitude_Begin) data.InsertNextValue(Latitude_End) fieldData.AddArray(data) data = vtk.vtkFloatArray() data.SetName('Longitude\nRange (deg)') data.InsertNextValue(Longitude_Begin) data.InsertNextValue(Longitude_End) fieldData.AddArray(data) data = vtk.vtkStringArray() data.SetName('Source') data.InsertNextValue(source) fieldData.AddArray(data) RenameSource(' '.join( [label.strip(), 'from', source.strip(), label2.strip()]))
def read_netCdfEarthModel(modelFile, latVariable, lonVariable, depthVariable, LL, UR, depthMin, depthMax, inc): """ read in an EMC Earth model in the netCDF format Parameters ---------- modelFile: str model file latVariable: str latitude variable lonVariable: str longitude variable depthVar: str depthVariable LL: list lower-left coordinate UR: list upper-right coordinate depthMin: float minimum depth depthMax: float maximum depth inc: int grid sampling interval Returns ------- X: float x-coordinate normalized to the radius of Earh Y: float y-coordinate normalized to the radius of Earh Z: float z-coordinate normalized to the radius of Earh meta: dict file metadata information """ #depthVariable = 'depth' #lonVariable = 'longitude' #latVariable = 'latitude' # # model data # NetCDF files, when opened read-only, return arrays that refer directly to memory-mapped data on disk: # import numpy as np from scipy.io import netcdf emcdata = netcdf.netcdf_file(modelFile, 'r') variables = [] for name in emcdata.variables.keys(): if name not in (depthVariable, lonVariable, latVariable): variables.append(name) # # I assume all variables are defined with uniform order of latitude, longitude and depth # var = variables[0] for i in range(len(emcdata.variables[var].dimensions)): if emcdata.variables[var].dimensions[i] == depthVariable: depthIndex = i elif emcdata.variables[var].dimensions[i] == lonVariable: lonIndex = i else: latIndex = i lat = emcdata.variables[latVariable][:].copy() lon = emcdata.variables[lonVariable][:].copy() for i in range(len(lon)): if lon[i] > 180.0: lon[i] -= 360.0 depth = emcdata.variables[depthVariable][:].copy() # # select the values within the ranges (this is to get a count only) # depth2 = [] latitude = [] longitude = [] depth2 = [] lastI = -1 for i in range(len(lon)): if i != 0 and i != len(lon) - 1 and i != lastI + inc: continue lastI = i for j in range(len(depth)): lastK = -1 for k in range(len(lat)): if k != 0 and k != len(lat) - 1 and k != lastK + inc: continue lastK = k if utils.isValueIn( lat[k], LL[0], UR[0]) and utils.isLongitudeIn( lon[i], LL[1], UR[1]) and utils.isValueIn( float(depth[j]), depthMin, depthMax): if lon[i] not in longitude: longitude.append(lon[i]) if depth[j] not in depth2: depth2.append(depth[j]) if lat[k] not in latitude: latitude.append(lat[k]) # # model data grid definition # V = {} nx = len(longitude) ny = len(depth2) nz = len(latitude) index = [-1, -1, -1] meta = { 'depth': [], 'lat': [100, -100], 'lon': [400, -400], 'source': modelFile } for l in range(len(variables)): X = np.zeros((nx, ny, nz)) Y = np.zeros((nx, ny, nz)) Z = np.zeros((nx, ny, nz)) v = np.zeros((nx, ny, nz)) var = variables[l] emcin = emcdata.variables[var][:].copy() latitude = [] longitude = [] depth2 = [] ii = -1 jj = -1 kk = -1 oldI = -1 oldJ = -1 oldK = -1 lastI = -1 for i in range(len(lon)): if i != 0 and i != len(lon) - 1 and i != lastI + inc: continue lastI = i for j in range(len(depth)): lastK = -1 for k in range(len(lat)): if k != 0 and k != len(lat) - 1 and k != lastK + inc: continue lastK = k if utils.isValueIn( lat[k], LL[0], UR[0]) and utils.isLongitudeIn( lon[i], LL[1], UR[1]) and utils.isValueIn( float(depth[j]), depthMin, depthMax): if i != oldI: meta['lon'] = [ min(meta['lon'][0], lon[i]), max(meta['lon'][0], lon[i]) ] oldI = i ii += 1 jj = -1 oldJ = -1 kk = -1 oldK = -1 if j != oldJ: if depth[j] not in meta['depth']: meta['depth'].append(depth[j]) oldJ = j jj += 1 kk = -1 oldK = -1 if k != oldK: meta['lat'] = [ min(meta['lat'][0], lat[k]), max(meta['lat'][0], lat[k]) ] oldK = k kk += 1 x, y, z = llz2xyz(lat[k], lon[i], depth[j] * depthFactor) X[ii, jj, kk] = x Y[ii, jj, kk] = y Z[ii, jj, kk] = z index[depthIndex] = j index[latIndex] = k index[lonIndex] = i v[ii, jj, kk] = emcin[index[0]][index[1]][index[2]] V[var] = v emcdata.close() return X, Y, Z, V, meta
def readSlabFile(modelFile, LL, UR, inc=5): """ read in a 2-D netCDF topo file Parameters ---------- modelFile: str model file LL: list lower-left coordinate UR: list upper-right coordinate inc: int grid sampling interval Returns ------- X: float x-coordinate normalized to the radius of Earh Y: float y-coordinate normalized to the radius of Earh Z: float z-coordinate normalized to the radius of Earh label: str file label """ zVariable = 'z' lonVariable = 'x' latVariable = 'y' depthFactor = -1 # # model data # import numpy as np from scipy.io import netcdf topodata = netcdf.netcdf_file(modelFile, 'r') lat = topodata.variables[latVariable][:].copy() lon = topodata.variables[lonVariable][:].copy() for i in range(len(lon)): if lon[i] > 180.0: lon[i] -= 360.0 elevData = topodata.variables[zVariable][:].copy() topodata.close() # # select the values within the ranges (this is to get a count only) # depth2 = [0] latitude = [] longitude = [] for i in range(0, len(lon), inc): for k in range(0, len(lat), inc): if utils.isValueIn(lat[k], LL[0], UR[0]) and utils.isLongitudeIn( lon[i], LL[1], UR[1]): if lon[i] not in longitude: longitude.append(lon[i]) if lat[k] not in latitude: latitude.append(lat[k]) # # model data grid definition # V = {} nx = len(longitude) ny = len(depth2) nz = len(latitude) index = [-1, -1, -1] label = "%0.1f-%0.1fkm" % (min(depth2), max(depth2)) for l in range(1): X = np.zeros((nx, ny, nz)) Y = np.zeros((nx, ny, nz)) Z = np.zeros((nx, ny, nz)) v = np.zeros((nx, ny, nz)) latitude = [] longitude = [] depth2 = [] ii = -1 jj = -1 kk = -1 oldI = -1 oldJ = -1 oldK = -1 for i in range(0, len(lon), inc): for j in range(1): for k in range(0, len(lat), inc): if utils.isValueIn(lat[k], LL[0], UR[0]) and utils.isLongitudeIn( lon[i], LL[1], UR[1]): if i != oldI: oldI = i ii += 1 oldJ = -1 kk = -1 oldK = -1 if k != oldK: oldK = k kk += 1 x, y, z = llz2xyz(lat[k], lon[i], elevData[k][i] * depthFactor) X[ii, j, kk] = x Y[ii, j, kk] = y Z[ii, j, kk] = z v[ii, j, kk] = elevData[k][i] V[zVariable] = v return X, Y, Z, V, label
def find2DnetCDFExtent(modelFile, latVar, lonVar, LL, UR, inc=1): """ find the extent of a 2-D netCDF as the number of grid points in each direction Parameters ---------- modelFile: str model file LL: list lower-left coordinate UR: list upper-right coordinate inc: int grid sampling interval Returns ------- ii: int number of element in the x-direction jj: int number of element in the y-direction kk: int number of element in the z-direction """ lonVariable = lonVar latVariable = latVar # # select the values within the ranges (this is to get a count only) # import numpy as np from scipy.io import netcdf twoDnetCDFdata = netcdf.netcdf_file(modelFile, 'r') lat = twoDnetCDFdata.variables[latVariable][:].copy() lon = twoDnetCDFdata.variables[lonVariable][:].copy() for i in range(len(lon)): if lon[i] > 180.0: lon[i] -= 360.0 twoDnetCDFdata.close() # # model data grid definition # for l in range(1): ii = 0 jj = 1 kk = 0 oldI = -1 oldJ = -1 oldK = -1 lastI = -1 lastK = -1 for i in range(len(lon)): if i != 0 and i != len(lon) - 1 and i != lastI + inc: continue lastI = i for k in range(len(lat)): if k != 0 and k != len(lat) - 1 and k != lastK + inc: continue lastK = k if utils.isValueIn(lat[k], LL[0], UR[0]) and utils.isLongitudeIn( lon[i], LL[1], UR[1]): if i != oldI: oldI = i ii += 1 oldJ = -1 kk = -1 oldK = -1 if k != oldK: oldK = k kk += 1 return ii, jj, kk
def RequestData(): # V.2019.079 import sys sys.path.insert(0, r'EMC_SRC_PATH') from paraview.simple import RenameSource, GetActiveViewOrCreate, ColorBy, GetDisplayProperties, GetActiveSource import numpy as np import csv import os from os.path import splitext from vtk.util import numpy_support as nps import IrisEMC_Paraview_Lib as lib import IrisEMC_Paraview_Utils as utils import IrisEMC_Paraview_Param as param File_name = File_name.strip() ext = None if File_name in list(param.filesDict.values()) or not ( File_name.lower().endswith(param.filesExtDict['ssl'].lower()) or File_name.lower().endswith(param.filesExtDict['geo'].lower())): if utils.support_nc(): ext = param.filesExtDict['ssl'] else: ext = param.filesExtDict['geo'] depth_begin = float(Depth_begin) depth_end = float(Depth_end) if depth_begin > depth_end: raise Exception('Begin Depth < End Depth! Aborting.') Latitude_begin, Latitude_end, Longitude_begin, Longitude_end = lib.get_area( Area, Latitude_begin, Latitude_end, Longitude_begin, Longitude_end) if len(Latitude_variable.strip()) <= 0 or len( Longitude_variable.strip()) <= 0 or len( Depth_variable.strip()) <= 0: raise Exception('Latitude, Longitude and Depth variable are required') # make sure we have input files fileFound, address, source = lib.find_file(File_name, loc=r'EMC_MODELS_PATH', ext=ext) if not fileFound: raise Exception('model file "' + address + '" not found! Aborting.') filename = lib.file_name(File_name) if len(Label.strip()) <= 0: if source == filename: Label = "%s " % (filename) else: Label = "%s from %s " % (filename, source) sg = self.GetOutput() # vtkPolyData this_filename, extension = splitext(address) if extension.lower() in ['.nc', '.grd']: X, Y, Z, V, meta = lib.read_netcdf_model( address, Latitude_variable, Longitude_variable, Depth_variable, (Latitude_begin, Longitude_begin), (Latitude_end, Longitude_end), depth_begin, depth_end, Vertical_Scaling, Sampling) else: try: X, Y, Z, V, meta = lib.read_geocsv_model_3d( address, (Latitude_begin, Longitude_begin), (Latitude_end, Longitude_end), depth_begin, depth_end, Vertical_Scaling, Sampling) except Exception as e: raise Exception('cannot recognize model file "' + address + '"! Aborting.\n' + str(e)) nx = len(X) if nx <= 0: raise Exception('No data found!') ny = len(X[0]) nz = len(X[0][0]) sg.SetDimensions(nx, ny, nz) # make geometry points = vtk.vtkPoints() for k in range(nz): for j in range(ny): for i in range(nx): points.InsertNextPoint((X[i, j, k], Y[i, j, k], Z[i, j, k])) sg.SetPoints(points) # make geometry count = 0 for var in list(V.keys()): scalars = vtk.vtkFloatArray() scalars.SetNumberOfComponents(1) scalars.SetName(var) for k in range(nz): for j in range(ny): for i in range(nx): if V[var][i, j, k] == float('nan'): scalars.InsertNextValue(float('nan')) else: scalars.InsertNextValue(V[var][i, j, k]) if count == 0: sg.GetPointData().SetScalars(scalars) else: sg.GetPointData().AddArray(scalars) count += 1 # store boundary metadata field_data = sg.GetFieldData() field_data.AllocateArrays(3) # number of fields data = vtk.vtkFloatArray() data.SetName('Latitude\nRange (deg)') data.InsertNextValue(meta['lat'][0]) data.InsertNextValue(meta['lat'][1]) field_data.AddArray(data) data = vtk.vtkFloatArray() data.SetName('Longitude\nRange (deg)') data.InsertNextValue(meta['lon'][0]) data.InsertNextValue(meta['lon'][1]) field_data.AddArray(data) data = vtk.vtkFloatArray() data.SetName('Depths (km)') for d in sorted(meta['depth']): data.InsertNextValue(d) field_data.AddArray(data) data = vtk.vtkStringArray() data.SetName('Source') data.InsertNextValue(File_name) field_data.AddArray(data) label_2 = " - %s (lat:%0.1f,%0.1f, lon:%0.1f,%0.1f, depth:%0.1f - %0.1f)" % ( lib.areaValues[Area], meta['lat'][0], meta['lat'][1], meta['lon'][0], meta['lon'][1], meta['depth'][0], meta['depth'][-1]) RenameSource(' '.join([Label.strip(), label_2.strip()])) sg.SetFieldData(field_data)
def read_geocsv_model_3d(model_file, ll, ur, depth_min, depth_max, roughness, inc, extent=False): """Read in a 3-D Earth model in the GeoCSV format. Keyword arguments: model_file: model file ll: lower-left coordinate ur: upper-right coordinate depth_min: minimum depth depth_max: maximum depth inc: grid sampling interval extent: provide model extent only (True or False) Return values: x: x-coordinate normalized to the radius of the Earth y: y-coordinate normalized to the radius of the Earth z: z-coordinate normalized to the radius of the Earth meta: file metadata information """ # model data and metadata (params, lines) = read_geocsv(model_file) # model data data = [] for line in lines: data.append(line.split(params['delimiter'])) # model variables depth_variable = params['depth_column'] lat_variable = params['latitude_column'] lon_variable = params['longitude_column'] elev_variable = params['elevation_column'] variables = [] for this_param in list(params.keys()): if params[this_param] not in ( depth_variable, lon_variable, lat_variable, elev_variable) and '_column' in this_param: variables.append(params[this_param]) # index to the variables var_index = {} for i, val in enumerate(params['header']): if val == depth_variable: depth_index = i elif val == lon_variable: lon_index = i elif val == lat_variable: lat_index = i else: var_index[val] = i lat = np.array(list(set(get_column(data, lat_index))), dtype=float) lon = np.array(list(set(get_column(data, lon_index))), dtype=float) # -180/180 models are the norm, so we convert 0/360 models to -180/180 first to unify # the rest of the code for all models data = np.ndarray.tolist(np.asfarray(data)) if utils.lon_is_360(lon): for i, values in enumerate(data): if float(values[lon_index]) > 180.0: data[i][lon_index] = float(values[lon_index]) - 360.0 lon = np.array(list(set(get_column(data, lon_index))), dtype=float) # we want the grid to be in x, y z order (longitude, depth, latitude) data.sort(key=itemgetter(lon_index, depth_index, lat_index)) lon.sort() lon, lon_map = utils.lon_180(lon, fix_gap=True) depth = np.array(list(set(get_column(data, depth_index))), dtype=float) # get coordinates sorted one last time lat.sort() lon.sort() depth.sort() # select the coordinates within the ranges (this is to get a count only) latitude = [] longitude = [] depth2 = [] last_i = -1 for i, lon_val in enumerate(lon): if i != 0 and i != len(lon) - 1 and i != last_i + inc: continue last_i = i for j, depth_val in enumerate(depth): last_k = -1 for k, lat_val in enumerate(lat): if k != 0 and k != len(lat) - 1 and k != last_k + inc: continue last_k = k if utils.isValueIn(float(lat_val), ll[0], ur[0]) and utils.isLongitudeIn( float(lon_val), ll[1], ur[1]) and \ utils.isValueIn(float(depth_val), depth_min, depth_max): if float(lon_map[utils.float_key( lon_val)]) not in longitude: longitude.append( float(lon_map[utils.float_key(lon_val)])) if float(depth_val) not in depth2: depth2.append(float(depth_val)) if float(lat_val) not in latitude: latitude.append(float(lat_val)) # model data grid definition V = {} nx = len(longitude) ny = len(depth2) nz = len(latitude) if extent: return nx - 1, ny - 1, nz - 1 meta = { 'depth': [], 'lat': [100, -100], 'lon': [400, -400], 'source': model_file } X = np.zeros((nx, ny, nz)) X[:] = np.nan Y = np.zeros((nx, ny, nz)) Y[:] = np.nan Z = np.zeros((nx, ny, nz)) Z[:] = np.nan for i, values in enumerate(data): lon_val = float(lon_map[utils.float_key(values[lon_index])]) lat_val = float(values[lat_index]) depth_val = float(values[depth_index]) if lon_val in longitude and lat_val in latitude and depth_val in depth2: meta['lon'] = [ min(meta['lon'][0], lon_val), max(meta['lon'][0], lon_val) ] meta['lat'] = [ min(meta['lat'][0], lat_val), max(meta['lat'][0], lat_val) ] if depth_val not in meta['depth']: meta['depth'].append(depth_val) x, y, z = llz2xyz(lat_val, lon_val, depth_val * roughness) ii = longitude.index(lon_val) jj = depth2.index(depth_val) kk = latitude.index(lat_val) X[ii, jj, kk] = x Y[ii, jj, kk] = y Z[ii, jj, kk] = z for l, var_val in enumerate(variables): if var_val not in list(V.keys()): V[var_val] = np.zeros((nx, ny, nz)) V[var_val][:] = np.nan if '_'.join([var_val, 'missing_value']) in params: # skip the designated missing_value if float(values[var_index[var_val]]) == float( params['_'.join([var_val, 'missing_value'])]): continue V[var_val][ii, jj, kk] = float(values[var_index[var_val]]) return X, Y, Z, V, meta
def find_file(address, loc, query='', ext=None): """find a file either locally or via a URL Keyword arguments: address: file address, path, url, etc. loc: location of the file query: URL query string Return values: found: indicating if the operation was a success address: full address of the local file source: where the file came from """ found = False # For default files, the calling script sends the proper extension to use depending on the OS support. if ext is not None: address = ''.join([address, ext]) if address.lower().endswith('.nc') and not utils.support_nc(): print( "[ERR] Cannot read netCDF files on this platform, try GeoCSV format!" ) return False, address, address # It is a full path to a file? source = address if os.path.isfile(address): origin = read_info_file(source) return True, address, origin # It is a file under the data directory? elif os.path.isfile(os.path.join(loc, address)): source = os.path.join(loc, address) origin = read_info_file(source) return True, source, origin # Other possibilities, URL? else: # Check the DMC URL. if loc in (pathDict['EMC_BOUNDARIES_PATH'], pathDict['EMC_MODELS_PATH'], pathDict['EMC_VOLCANOES_PATH']): source = irisEMC_Files_URL + address if is_url_valid(source): found, destination, origin = get_file_from_url( source, loc, filename=os.path.join(loc, address)) # USGS Slab 1.0 elif loc == pathDict['EMC_SLABS_PATH']: source = usgsSlab_URL + address if is_url_valid(source): found, destination, origin = get_file_from_url( source, loc, filename=os.path.join(loc, address)) # Earthquakes. elif loc == pathDict['EMC_EARTHQUAKES_PATH']: source = query if is_url_valid(source): found, destination, origin = get_file_from_url( source, loc, filename=os.path.join(loc, address)) if found: fp = open(destination, 'r+') catalog = fp.read() fp.seek(0, 0) fp.write(eq_header(source)) fp.write(catalog) fp.close() # Did we find the file? if found: return found, destination, origin # Did user provide a URL. else: found, destination, origin = get_file_from_url(address, loc, query) return found, destination, origin
def read_netcdf_topo_file(model_file, ll, ur, inc, roughness, lon_var='longitude', lat_var='latitude', elev_var='elevation', base=0, unit_factor=1, extent=False): """read in etopo, a 2-D netCDF topo file Keyword arguments: model_file: model file ll: lower-left coordinate ur: upper-right coordinate inc: grid sampling interval roughness: set the variable as depth and use this for exaggeration extent: should only compute model extent? (True or False) RReturn values: X: x-coordinate normalized to the radius of Earh Y: y-coordinate normalized to the radius of Earh Z: z-coordinate normalized to the radius of Earh label: file label """ # ParaView on some platforms does not have SciPy module if not utils.support_nc(): print("[ERR] Sorry, cannot read netCDF files on this platform!") return 0, 0, 0 z_variable = elev_var lon_variable = lon_var lat_variable = lat_var depth = base # model data data = netcdf.netcdf_file(model_file, 'r') lat = data.variables[lat_variable][:].copy() lon = data.variables[lon_variable][:].copy() lon = utils.lon_180(lon) elevation_data = data.variables[z_variable][:].copy() data.close() dep = [depth] variables = [z_variable] # select the values within the ranges (this is to get a count only) latitude, longitude, depth2 = get_points_in_area(lat, lon, dep, ll, ur, inc) # model data grid definition V = {} nx = len(longitude) ny = len(depth2) nz = len(latitude) if extent: return nx - 1, ny - 1, nz - 1 label = '' if hasattr(data, 'description'): label = data.description elif hasattr(data, 'title'): label = data.title for l, var_value in enumerate(variables): X = np.zeros((nx, ny, nz)) Y = np.zeros((nx, ny, nz)) Z = np.zeros((nx, ny, nz)) v = np.zeros((nx, ny, nz)) for i, lon_val in enumerate(lon): for j, depth_val in enumerate(dep): for k, lat_val in enumerate(lat): if lon_val in longitude and lat_val in latitude and depth_val in depth2: ii = longitude.index(lon_val) jj = depth2.index(depth_val) kk = latitude.index(lat_val) # "+" since it is elevation but we already making roughness negative to make it positive up x, y, z = llz2xyz( lat_val, lon_val, depth_val + (elevation_data[k][i] * roughness * unit_factor)) X[ii, jj, kk] = x Y[ii, jj, kk] = y Z[ii, jj, kk] = z v[ii, jj, kk] = elevation_data[k][i] * float(unit_factor) V[z_variable] = v return X, Y, Z, V, label
def read_slab_file(model_file, ll, ur, inc=1, depth_factor=-1, extent=False): """read in a 2-D netCDF Slab file Keyword arguments: model_file: model file ll: lower-left coordinate ur: upper-right coordinate inc: grid sampling interval RReturn values: X: x-coordinate normalized to the radius of Earh Y: y-coordinate normalized to the radius of Earh Z: z-coordinate normalized to the radius of Earh label: file label """ # ParaView on some systems does not have SciPy module if not utils.support_nc(): print( "[ERR] Cannot read netCDF files on this platform, try GeoCSV format!" ) return [], [], [], [], '' z_variable = 'z' lon_variable = 'x' lat_variable = 'y' depth = 0 # model data data = netcdf.netcdf_file(model_file, 'r') lat = data.variables[lat_variable][:].copy() lon = data.variables[lon_variable][:].copy() lon = utils.lon_180(lon) elevation_data = data.variables[z_variable][:].copy() data.close() dep = [depth] variables = [z_variable] # select the values within the ranges (this is to get a count only) latitude, longitude, depth2 = get_points_in_area(lat, lon, dep, ll, ur, inc) # model data grid definition V = {} nx = len(longitude) ny = len(depth2) nz = len(latitude) if extent: return nx - 1, ny - 1, nz - 1 label = '' if len(depth2): label = "%0.1f-%0.1fkm" % (min(depth2), max(depth2)) for l, var_value in enumerate(variables): X = np.zeros((nx, ny, nz)) Y = np.zeros((nx, ny, nz)) Z = np.zeros((nx, ny, nz)) v = np.zeros((nx, ny, nz)) for i, lon_val in enumerate(lon): for j, depth_val in enumerate(dep): for k, lat_val in enumerate(lat): if lon_val in longitude and lat_val in latitude and depth_val in depth2: ii = longitude.index(lon_val) jj = depth2.index(depth_val) kk = latitude.index(lat_val) x, y, z = llz2xyz(lat[k], lon[i], elevation_data[k][i] * depth_factor) X[ii, jj, kk] = x Y[ii, jj, kk] = y Z[ii, jj, kk] = z v[ii, jj, kk] = elevation_data[k][i] V[z_variable] = v return X, Y, Z, V, label
def read2DnetCDFFile(modelFile, latVariable, lonVariable, variable, LL, UR, inc, setDepth=None): """ read in a 2-D netCDF file Parameters ---------- modelFile: str model file latVar: str latitude variable lonVar: str longitude variable var: str variable to plot LL: list lower-left coordinate UR: list upper-right coordinate inc: int grid sampling interval depth: float depth to plot var at. If None, use var also as depth Returns ------- X: float x-coordinate normalized to the radius of Earh Y: float y-coordinate normalized to the radius of Earh Z: float z-coordinate normalized to the radius of Earh meta: dict file metadata information """ # # model data # NetCDF files, when opened read-only, return arrays that refer directly to memory-mapped data on disk: # import numpy as np from scipy.io import netcdf emcdata = netcdf.netcdf_file(modelFile, 'r') variables = [] for name in emcdata.variables.keys(): if name not in (lonVariable, latVariable): variables.append(name) # # I assume all variables are defined with uniform order of latitude and longitude # var = variables[0] for i in range(len(emcdata.variables[var].dimensions)): if emcdata.variables[var].dimensions[i] == lonVariable: lonIndex = i else: latIndex = i lat = emcdata.variables[latVariable][:].copy() lon = emcdata.variables[lonVariable][:].copy() for i in range(len(lon)): if lon[i] > 180.0: lon[i] -= 360.0 depth = [0, 1] # # select the values within the ranges (this is to get a count only) # depth2 = [] latitude = [] longitude = [] depth2 = [] lastI = -1 for i in range(len(lon)): if i != 0 and i != len(lon) - 1 and i != lastI + inc: continue lastI = i for j in range(len(depth)): lastK = -1 for k in range(len(lat)): if k != 0 and k != len(lat) - 1 and k != lastK + inc: continue lastK = k if utils.isValueIn(lat[k], LL[0], UR[0]) and utils.isLongitudeIn( lon[i], LL[1], UR[1]): if lon[i] not in longitude: longitude.append(lon[i]) if depth[j] not in depth2: depth2.append(depth[j]) if lat[k] not in latitude: latitude.append(lat[k]) # # model data grid definition # V = {} nx = len(longitude) ny = len(depth2) nz = len(latitude) index = [-1, -1, -1] meta = { 'depth': [], 'lat': [100, -100], 'lon': [400, -400], 'source': modelFile } for l in range(len(variables)): X = np.zeros((nx, ny, nz)) Y = np.zeros((nx, ny, nz)) Z = np.zeros((nx, ny, nz)) v = np.zeros((nx, ny, nz)) var = variables[l] emcin = emcdata.variables[var][:].copy() latitude = [] longitude = [] depth2 = [] ii = -1 jj = -1 kk = -1 oldI = -1 oldJ = -1 oldK = -1 lastI = -1 for i in range(len(lon)): if i != 0 and i != len(lon) - 1 and i != lastI + inc: continue lastI = i for j in range(len(depth)): lastK = -1 for k in range(len(lat)): if k != 0 and k != len(lat) - 1 and k != lastK + inc: continue lastK = k if utils.isValueIn(lat[k], LL[0], UR[0]) and utils.isLongitudeIn( lon[i], LL[1], UR[1]): if i != oldI: meta['lon'] = [ min(meta['lon'][0], lon[i]), max(meta['lon'][0], lon[i]) ] oldI = i ii += 1 jj = -1 oldJ = -1 kk = -1 oldK = -1 if j != oldJ: if depth[j] not in meta['depth']: meta['depth'].append(depth[j]) oldJ = j jj += 1 kk = -1 oldK = -1 if k != oldK: meta['lat'] = [ min(meta['lat'][0], lat[k]), max(meta['lat'][0], lat[k]) ] oldK = k kk += 1 index[latIndex] = k index[lonIndex] = i thisValue = emcin[index[0]][index[1]] if thisValue <= -990 or thisValue > 9999: thisValue = None if thisValue is None: v[ii, jj, kk] = None else: v[ii, jj, kk] = float(thisValue) if setDepth is None: if thisValue is None: thisDepth = 0 else: thisDepth = float(thisValue) else: thisDepth = float(thisValue) x, y, z = llz2xyz(lat[k], lon[i], thisDepth) X[ii, jj, kk] = x Y[ii, jj, kk] = y Z[ii, jj, kk] = z V[var] = v emcdata.close() return X, Y, Z, V, meta
def read_geocsv_model_2d(model_file, ll, ur, inc, roughness, unit_factor=1, base=0, extent=False): """Read in a 3-D Earth model in the GeoCSV format. Keyword arguments: model_file: model file ll: lower-left coordinate ur: upper-right coordinate inc: grid sampling interval roughness: set the variable as depth and use this for exaggeration extent: should only compute model extent? (True or False) Return values: x: x-coordinate normalized to the radius of the Earth y: y-coordinate normalized to the radius of the Earth z: z-coordinate normalized to the radius of the Earth meta: file metadata information """ # model data and metadata (params, lines) = read_geocsv(model_file, is_2d=True) # model data raw_data = [] for line in lines: raw_data.append(line.split(params['delimiter'])) data = [list(utils.str2float(sublist)) for sublist in raw_data] # model variables variables = [] for this_param in list(params.keys()): if params[this_param] not in ( params['longitude_column'], params['latitude_column']) and '_column' in this_param: variables.append(params[this_param]) # index to the variables var_index = {} for i, val in enumerate(params['header']): if val == params['longitude_column']: lon_index = i elif val == params['latitude_column']: lat_index = i else: for this_var in variables: if val == params[this_var + '_column']: var_index[this_var] = i break lat = list(set(get_column(data, lat_index))) lon = list(set(get_column(data, lon_index))) lon.sort(key=float) lon, lon_map = utils.lon_180(lon, fix_gap=True) depth = [base] # get coordinates sorted otherwise inc will not function properly lat.sort(key=float) lon.sort(key=float) # select the values within the ranges (this is to get a count only) latitude, longitude, depth2 = get_points_in_area(lat, lon, depth, ll, ur, inc) # model data grid definition V = {} nx = len(longitude) ny = len(depth2) nz = len(latitude) if extent: return nx - 1, ny - 1, nz - 1 meta = { 'depth': [], 'lat': [100, -100], 'lon': [400, -400], 'source': model_file } for l, var_val in enumerate(variables): X = np.zeros((nx, ny, nz)) X[:] = np.nan Y = np.zeros((nx, ny, nz)) Y[:] = np.nan Z = np.zeros((nx, ny, nz)) Z[:] = np.nan # we want the grid to be in x, y z order (longitude, depth, latitude) data.sort(key=itemgetter(lat_index, lon_index)) for i, values in enumerate(data): lon_val = float(lon_map[utils.float_key(values[lon_index])]) lat_val = float(values[lat_index]) this_value = float(values[var_index[var_val]]) if this_value is None: depth_val = base else: depth_val = base + float(this_value) * float( roughness) * float(unit_factor) if lon_val in longitude and lat_val in latitude: meta['lon'] = [ min(meta['lon'][0], lon_val), max(meta['lon'][0], lon_val) ] meta['lat'] = [ min(meta['lat'][0], lat_val), max(meta['lat'][0], lat_val) ] if depth_val not in meta['depth']: meta['depth'].append(depth_val) x, y, z = llz2xyz(lat_val, lon_val, depth_val) ii = longitude.index(lon_val) jj = 0 kk = latitude.index(lat_val) X[ii, jj, kk] = x Y[ii, jj, kk] = y Z[ii, jj, kk] = z if var_val not in list(V.keys()): V[var_val] = np.zeros((nx, ny, nz)) V[var_val][:] = np.nan if '_'.join([var_val, 'missing_value']) in params: # skip the designated missing_value if float(this_value) == float(params['_'.join( [var_val, 'missing_value'])]): continue V[var_val][ii, jj, kk] = float(this_value) return X, Y, Z, V, meta
def readTopoFile(modelFile, LL, UR, inc): """ read in etopo5, a 2-D netCDF topo file Parameters ---------- modelFile: str model file LL: list lower-left coordinate UR: list upper-right coordinate inc: int grid sampling interval Returns ------- X: float x-coordinate normalized to the radius of Earh Y: float y-coordinate normalized to the radius of Earh Z: float z-coordinate normalized to the radius of Earh label: str file label """ zVariable = 'elev' lonVariable = 'X' latVariable = 'Y' # # model data # import numpy as np from scipy.io import netcdf topodata = netcdf.netcdf_file(modelFile, 'r') lat = topodata.variables[latVariable][:].copy() lon = topodata.variables[lonVariable][:].copy() for i in range(len(lon)): if lon[i] > 180.0: lon[i] -= 360.0 elevData = topodata.variables[zVariable][:].copy() topodata.close() # # select the values within the ranges (this is to get a count only) # depth2 = [0] latitude = [] longitude = [] # # the loop is intended to include that last lat and lon regardless of inc # lastI = -1 for i in range(len(lon)): if i != 0 and i != len(lon) - 1 and i != lastI + inc: continue lastI = i lastK = -1 for k in range(len(lat)): if k != 0 and k != len(lat) - 1 and k != lastK + inc: continue lastK = k if utils.isValueIn(lat[k], LL[0], UR[0]) and utils.isLongitudeIn( lon[i], LL[1], UR[1]): if lon[i] not in longitude: longitude.append(lon[i]) if lat[k] not in latitude: latitude.append(lat[k]) # # model data grid definition # V = {} nx = len(longitude) ny = len(depth2) nz = len(latitude) index = [-1, -1, -1] label = topodata.description for l in range(1): X = np.zeros((nx, ny, nz)) Y = np.zeros((nx, ny, nz)) Z = np.zeros((nx, ny, nz)) v = np.zeros((nx, ny, nz)) latitude = [] longitude = [] depth2 = [] ii = -1 jj = -1 kk = -1 oldI = -1 oldJ = -1 oldK = -1 lastI = -1 for i in range(len(lon)): if i != 0 and i != len(lon) - 1 and i != lastI + inc: continue lastI = i for j in range(1): lastK = -1 for k in range(len(lat)): if k != 0 and k != len(lat) - 1 and k != lastK + inc: continue lastK = k if utils.isValueIn(lat[k], LL[0], UR[0]) and utils.isLongitudeIn( lon[i], LL[1], UR[1]): if i != oldI: oldI = i ii += 1 oldJ = -1 kk = -1 oldK = -1 if k != oldK: oldK = k kk += 1 x, y, z = llz2xyz( lat[k], lon[i], elevData[k][i] * depthFactor / 1000.0) X[ii, j, kk] = x Y[ii, j, kk] = y Z[ii, j, kk] = z v[ii, j, kk] = elevData[k][i] V[zVariable] = v return X, Y, Z, V, label
def RequestData(): # V.2019.031 import sys sys.path.insert(0, r'EMC_SRC_PATH') import paraview.simple as simple import numpy as np import csv import os import datetime from vtk.util import numpy_support as nps import IrisEMC_Paraview_Lib as Lib import IrisEMC_Paraview_Utils as Utils import urllib.parse pts = vtk.vtkPoints() Latitude_Begin, Latitude_End, Longitude_Begin, Longitude_End = Lib.get_area( Area, Latitude_Begin, Latitude_End, Longitude_Begin, Longitude_End) label2 = " - %s (lat:%0.1f,%0.1f, lon:%0.1f,%0.1f, depth:%0.1f-%0.1f)" % ( Lib.areaValues[Area], Latitude_Begin, Latitude_End, Longitude_Begin, Longitude_End, Depth_Begin, Depth_End) # make sure we have input files if not Time_End.strip(): Time_End = datetime.datetime.today().strftime('%Y-%m-%d') query = Lib.earthquakeQuery % (Time_Begin, Time_End, Magnitude_Begin, Magnitude_End, Depth_Begin, Depth_End, Latitude_Begin, Latitude_End, Longitude_Begin, Longitude_End) Alternate_FileName = Alternate_FileName.strip() if len(Alternate_FileName) <= 0: eqFile = Lib.query2filename(query, url=Lib.earthquakeKeys[Data_Source]) query = '?'.join([Lib.earthquakeKeys[Data_Source], query]) fileFound, address, source = Lib.find_file(eqFile, loc=r'EMC_EARTHQUAKES_PATH', query=query) else: fileFound, address, source = Lib.find_file(Alternate_FileName, loc=r'EMC_EARTHQUAKES_PATH') if not fileFound: raise Exception( 'earthquake catalog file "' + address + '" not found! Please provide the full path or UR for the file. Aborting.' ) (params, lines) = Lib.read_geocsv(address) pdo = self.GetOutput() # vtkPoints column_keys = Lib.columnKeys for key in list(Lib.columnKeys.keys()): if key in list(params.keys()): column_keys[key] = params[key] origin = None if 'source' in params: origin = params['source'] this_label = urllib.parse.urlparse(origin).netloc else: try: this_label = urllib.parse.urlparse(Alternate_FileName).netloc except: this_label = Alternate_FileName header = params['header'] lat_index = None lon_index = None depth_index = None mag_index = None time_index = None for index, value in enumerate(header): if value.strip().lower() == column_keys['longitude_column'].lower(): lon_index = index elif value.strip().lower() == column_keys['latitude_column'].lower(): lat_index = index elif value.strip().lower() == column_keys['depth_column'].lower(): depth_index = index elif value.strip().lower() == column_keys['magnitude_column'].lower(): mag_index = index elif value.strip().lower() == column_keys['time_column'].lower(): time_index = index scalar_m = vtk.vtkFloatArray() scalar_m.SetNumberOfComponents(1) scalar_m.SetName("magnitude") scalar_d = vtk.vtkFloatArray() scalar_d.SetNumberOfComponents(1) scalar_d.SetName("depth") scalar_t = vtk.vtkLongArray() scalar_t.SetNumberOfComponents(1) scalar_t.SetName("year-month") lat = [] lon = [] depth = [] mag = [] time = [] frame_tag = Frame_Tag.strip() frame = dict() frame_single = dict() frame_key = Frame_Length_sec for i in range(len(lines)): line = lines[i].strip() values = line.strip().split(params['delimiter'].strip()) lat_value = float(values[lat_index]) lat.append(lat_value) lon_value = float(values[lon_index]) lon.append(lon_value) depth_value = float(values[depth_index]) depth.append(depth_value) mag_value = float(values[mag_index]) mag.append(mag_value) time_value = values[time_index] time.append(time_value) # check conditions again in case data came from a file if not (float(Latitude_Begin) <= lat_value <= float(Latitude_End) and float(Longitude_Begin) <= lon_value <= float(Longitude_End) and float(Depth_Begin) <= depth_value <= float(Depth_End) and float(Magnitude_Begin) <= mag_value <= float(Magnitude_End)): continue if Latitude_Begin <= lat[-1] <= Latitude_End and Longitude_Begin <= lon[ -1] <= Longitude_End: x, y, z = Lib.llz2xyz(lat[-1], lon[-1], depth[-1]) pts.InsertNextPoint(x, y, z) scalar_m.InsertNextValue(mag[-1]) scalar_d.InsertNextValue(depth[-1]) day_value = Utils.datetime_to_int(time[-1], level='day') scalar_t.InsertNextValue(day_value) if frame_tag: frame_time = int( Utils.datetime_to_float(time_value) - Utils.datetime_to_float(Time_Begin)) if frame_time < frame_key: frame[str(frame_key)] = '%s\n%f,%f,%f,%0.2f,%0.1f,%d' % ( frame[str(frame_key)], x, y, z, depth[-1], mag[-1], day_value) if frame_time >= frame_key - Frame_Length_sec: frame_single[str( frame_key)] = '%s\n%f,%f,%f,%0.2f,%0.1f,%d' % ( frame_single[str(frame_key)], x, y, z, depth[-1], mag[-1], day_value) else: frame_key += Frame_Length_sec frame[str(frame_key)] = '%f,%f,%f,%0.2f,%0.1f,%d' % ( x, y, z, depth[-1], mag[-1], day_value) frame_single[str( frame_key)] = '%f,%f,%f,%0.2f,%0.1f,%d' % ( x, y, z, depth[-1], mag[-1], day_value) # save animation frames if frame_tag: Utils.remove_files( os.path.join('EMC_EQ_ANIMATION_PATH', '%s_*.txt') % frame_tag) key_list = [int(x) for x in list(frame.keys())] key_list.sort() key0 = key_list[0] eq_list = 'X,Y,Z,Depth,Mag,Year-Month' for i, key in enumerate(key_list): eq_list = '%s\n%s' % (eq_list, frame[str(key)]) with open( os.path.join('EMC_EQ_ANIMATION_PATH', '%s_%012d.txt' % (frame_tag, key - key0)), 'w') as fp: fp.write('%s' % eq_list) eq = 'X,Y,Z,Depth,Mag,Year-Month\n%s' % frame_single[str(key)] with open( os.path.join( 'EMC_EQ_ANIMATION_PATH', '%s_single_%012d.txt' % (frame_tag, key - key0)), 'w') as fp: fp.write('%s' % eq) pdo.SetPoints(pts) pdo.GetPointData().AddArray(scalar_m) pdo.GetPointData().AddArray(scalar_d) pdo.GetPointData().AddArray(scalar_t) if len(this_label.strip()) > 0: simple.RenameSource(' '.join([ 'Earthquake locations:', 'from', this_label.strip(), label2.strip() ])) # store metadata field_data = pdo.GetFieldData() field_data.AllocateArrays(3) # number of fields data = vtk.vtkFloatArray() data.SetName('Latitude\nRange (deg)') data.InsertNextValue(min(lat)) data.InsertNextValue(max(lat)) field_data.AddArray(data) data = vtk.vtkFloatArray() data.SetName('Longitude\nRange (deg)') data.InsertNextValue(min(lon)) data.InsertNextValue(max(lon)) field_data.AddArray(data) data = vtk.vtkFloatArray() data.SetName('Depth\nRange (km)') data.InsertNextValue(min(depth)) data.InsertNextValue(max(depth)) field_data.AddArray(data) data = vtk.vtkFloatArray() data.SetName('Magnitude\nRange') data.InsertNextValue(min(mag)) data.InsertNextValue(max(mag)) field_data.AddArray(data) data = vtk.vtkIntArray() data.SetName('Max. Event\nCount') data.InsertNextValue(len(mag)) field_data.AddArray(data) data = vtk.vtkStringArray() data.SetName('Start Date') data.InsertNextValue(Time_Begin) field_data.AddArray(data) data = vtk.vtkStringArray() data.SetName('End Date') data.InsertNextValue(Time_End) field_data.AddArray(data) data = vtk.vtkStringArray() data.SetName('Source') if origin is not None: data.InsertNextValue(origin) data.InsertNextValue(source) field_data.AddArray(data) pdo.SetFieldData(field_data)
def getSlabExtent(modelFile, LL, UR, inc=5): """ find the extent of a 2-D top model file in netCDF format as the number of grid points in each direction Parameters ---------- modelFile: str model file LL: list lower-left coordinate UR: list upper-right coordinate inc: int grid sampling interval Returns ------- ii: int number of element in the x-direction jj: int number of element in the y-direction kk: int number of element in the z-direction """ depthVariable = 'z' lonVariable = 'x' latVariable = 'y' # # select the values within the ranges (this is to get a count only) # import numpy as np from scipy.io import netcdf topodata = netcdf.netcdf_file(modelFile, 'r') lat = topodata.variables[latVariable][:].copy() lon = topodata.variables[lonVariable][:].copy() for i in range(len(lon)): if lon[i] > 180.0: lon[i] -= 360.0 depth = topodata.variables[depthVariable][:].copy() topodata.close() # # model data grid definition # for l in range(1): ii = 0 jj = 1 kk = 0 oldI = -1 oldJ = -1 oldK = -1 for i in range(0, len(lon), inc): for k in range(0, len(lat), inc): if utils.isValueIn(lat[k], LL[0], UR[0]) and utils.isLongitudeIn( lon[i], LL[1], UR[1]): if i != oldI: oldI = i ii += 1 oldJ = -1 kk = -1 oldK = -1 if k != oldK: oldK = k kk += 1 return ii, jj, kk
def RequestData(): # R.1.2018.346 import sys sys.path.insert(0, r'EMC_SRC_PATH') from paraview.simple import RenameSource, GetActiveViewOrCreate, ColorBy, GetDisplayProperties, GetActiveSource import numpy as np import csv import os from os.path import splitext from vtk.util import numpy_support as nps import IrisEMC_Paraview_Lib as lib import urllib.parse import IrisEMC_Paraview_Utils as utils import IrisEMC_Paraview_Param as param USGS = True if len(Alternate_FileName.strip()) > 0: FileName = Alternate_FileName.strip() Label = ' '.join(['SLAB', lib.file_name(Alternate_FileName).strip()]) USGS = False else: FileName = lib.usgsSlabKeys[Slab] FileName = FileName.strip() ext = None if FileName in list(param.usgsSlabDict.keys()): if utils.support_nc(): ext = param.usgsSlabExtDict['ssl'] else: ext = param.usgsSlabExtDict['geo'] depthFactor = -1 Latitude_Begin, Latitude_End, Longitude_Begin, Longitude_End = lib.get_area( Area, Latitude_Begin, Latitude_End, Longitude_Begin, Longitude_End) Label2 = " - %s (lat:%0.1f,%0.1f, lon:%0.1f,%0.1f)" % ( lib.areaValues[Area], Latitude_Begin, Latitude_End, Longitude_Begin, Longitude_End, ) # Make sure we have input files fileFound, address, source = lib.find_file(FileName, loc=r'EMC_SLABS_PATH', ext=ext) if not fileFound: raise Exception('model file "' + address + '" not found! Aborting.') this_filename, extension = splitext(address) sg = self.GetOutput() # vtkPolyData if extension.lower() == '.grd': X, Y, Z, V, label = lib.read_slab_file( address, (Latitude_Begin, Longitude_Begin), (Latitude_End, Longitude_End), inc=Sampling, depth_factor=depthFactor, extent=False) elif extension.lower() == '.csv': X, Y, Z, V, meta = lib.read_geocsv_model_2d( address, (Latitude_Begin, Longitude_Begin), (Latitude_End, Longitude_End), Sampling, 1, base=0, unit_factor=depthFactor, extent=False) label = '' else: raise Exception('cannot recognize model file "' + address + '"! Aborting.') nx = len(X) ny = len(X[0]) nz = len(X[0][0]) sg.SetDimensions(nx, ny, nz) # # make geometry # points = vtk.vtkPoints() for k in range(nz): for j in range(ny): for i in range(nx): points.InsertNextPoint((X[i, j, k], Y[i, j, k], Z[i, j, k])) sg.SetPoints(points) # # make geometry # count = 0 for var in list(V.keys()): scalars = vtk.vtkFloatArray() scalars.SetNumberOfComponents(1) scalars.SetName(var) for k in range(nz): for j in range(ny): for i in range(nx): scalars.InsertNextValue(depthFactor * V[var][i, j, k]) if count == 0: sg.GetPointData().SetScalars(scalars) else: sg.GetPointData().AddArray(scalars) count += 1 # store USGS metadata if USGS: fieldData = sg.GetFieldData() fieldData.AllocateArrays(3) # number of fields data = vtk.vtkFloatArray() data.SetName('Latitude\nRange (deg)') data.InsertNextValue( lib.usgsSlabRangeDict[lib.usgsSlabKeys[Slab]]['Y'][0]) data.InsertNextValue( lib.usgsSlabRangeDict[lib.usgsSlabKeys[Slab]]['Y'][1]) fieldData.AddArray(data) data = vtk.vtkFloatArray() data.SetName('Longitude\nRange (deg)') minX = lib.usgsSlabRangeDict[lib.usgsSlabKeys[Slab]]['X'][0] if minX > 180: minX -= 360 maxX = lib.usgsSlabRangeDict[lib.usgsSlabKeys[Slab]]['X'][1] if maxX > 180: maxX -= 360 xMin = min([minX, maxX]) xMax = max([minX, maxX]) data.InsertNextValue(xMin) data.InsertNextValue(xMax) fieldData.AddArray(data) data = vtk.vtkFloatArray() data.SetName('Depth to Slab\nRange (km)') data.InsertNextValue( abs(lib.usgsSlabRangeDict[lib.usgsSlabKeys[Slab]]['Z'][1])) data.InsertNextValue( abs(lib.usgsSlabRangeDict[lib.usgsSlabKeys[Slab]]['Z'][0])) fieldData.AddArray(data) data = vtk.vtkStringArray() data.SetName('Source') data.InsertNextValue(lib.usgsSlab_URL) Label = ' '.join([ 'USGS Slab 1.0:', lib.usgsSlabValues[Slab].strip(), 'from', urllib.parse.urlparse(lib.usgsSlab_URL).netloc.strip() ]) data.InsertNextValue(lib.usgsSlabKeys[Slab]) fieldData.AddArray(data) RenameSource(' '.join([Label.strip(), Label2.strip()]))
def find_netCDFModelExtent(modelFile, latVariable, lonVariable, depthVariable, LL, UR, depthMin, depthMax, inc): """ find the extent of the model as the number of grid points in each direction Parameters ---------- modelFile: str model file latVariable: str latitude variable lonVariable: str longitude variable depthVar: str depthVariable LL: list lower-left coordinate UR: list upper-right coordinate depthMin: float minimum depth depthMax: float maximum depth inc: int grid sampling interval Returns ------- ii: int number of element in the x-direction jj: int number of element in the y-direction kk: int number of element in the z-direction """ #depthVariable = 'depth' #lonVariable = 'longitude' #latVariable = 'latitude' # # model data # import numpy as np from scipy.io import netcdf emcdata = netcdf.netcdf_file(modelFile, 'r') variables = [] for name in emcdata.variables.keys(): if name not in (depthVariable, lonVariable, latVariable): variables.append(name) # # I assume all variables are defined with uniform order of latitude, longitude and depth # var = variables[0] for i in range(len(emcdata.variables[var].dimensions)): if emcdata.variables[var].dimensions[i] == depthVariable: depthIndex = i elif emcdata.variables[var].dimensions[i] == lonVariable: lonIndex = i else: latIndex = i lat = emcdata.variables[latVariable][:].copy() lon = emcdata.variables[lonVariable][:].copy() for i in range(len(lon)): if lon[i] > 180.0: lon[i] -= 360.0 depth = emcdata.variables[depthVariable][:].copy() emcdata.close() # # model data grid definition # for l in range(len(variables)): ii = -1 jj = -1 kk = -1 oldI = -1 oldJ = -1 oldK = -1 lastI = -1 for i in range(len(lon)): if i != 0 and i != len(lon) - 1 and i != lastI + inc: continue lastI = i for j in range(len(depth)): lastK = -1 for k in range(len(lat)): if k != 0 and k != len(lat) - 1 and k != lastK + inc: continue lastK = k if utils.isValueIn( lat[k], LL[0], UR[0]) and utils.isLongitudeIn( lon[i], LL[1], UR[1]) and utils.isValueIn( float(depth[j]), depthMin, depthMax): if i != oldI: oldI = i ii += 1 jj = -1 oldJ = -1 kk = -1 oldK = -1 if j != oldJ: oldJ = j jj += 1 kk = -1 oldK = -1 if k != oldK: oldK = k kk += 1 return ii, jj, kk
pathDict = { 'EMC_MAIN_PATH': topDir, 'EMC_PLUGINS_PATH': os.path.join(topDir, 'plugins'), 'EMC_MACROS_PATH': os.path.join(topDir, 'macros'), 'EMC_SRC_PATH': os.path.join(topDir, 'src'), 'EMC_DATA_PATH': os.path.join(topDir, 'data'), 'EMC_SCRATCH_PATH': os.path.join(topDir, 'data', 'scratch'), 'EMC_SLABS_PATH': os.path.join(topDir, 'data', 'slabs'), 'EMC_MODELS_PATH': os.path.join(topDir, 'data', 'models'), 'EMC_BOUNDARIES_PATH': os.path.join(topDir, 'data', 'boundaries'), 'EMC_VOLCANOES_PATH': os.path.join(topDir, 'data', 'volcanoes'), 'EMC_EARTHQUAKES_PATH': os.path.join(topDir, 'data', 'earthquakes') } for key in pathDict.keys(): utils.makePath(pathDict[key]) # # default files # filesDict = { 'ETOPO5': 'etopo5.nc', 'EMC_DEFAULT_MODEL': 'wUS-SH-2010_percent.nc', 'EMC_DEFAULT_2DMODEL': 'CAM2016Litho.nc' } # # default column names for GeoCSV files. User can redefine these in the GeoCSV header # columnKeys = { 'latitude_column': 'latitude',