def test_scalar_lin(lin, field='tens', cmap=plt.cm.jet): #{{{ import lineament satfile="input/ConvectingEuropa_GlobalDiurnalNSR.ssrun" europa = ss.Satellite(open(satfile,'r')) NSR = ss.StressCalc([ss.NSR(europa),]) mp_lons, mp_lats = lin.seg_midpoints() seg_lengths = lin.seg_lengths() min_lat = 0 max_lat = np.pi/2.0 min_lon = 0.0 max_lon = np.pi the_fig = plt.figure(figsize=(10,10)) map_ax = the_fig.add_subplot(1,1,1) map_ax.set_title("Point by Point scalar stresses field (%s)" % (field,) ) scalar_basemap = basemap.Basemap(llcrnrlon = np.degrees(min_lon),\ llcrnrlat = np.degrees(min_lat),\ urcrnrlon = np.degrees(max_lon),\ urcrnrlat = np.degrees(max_lat),\ ax = map_ax) scalar_points(stresscalc=NSR, lons=np.mod(mp_lons,np.pi), lats=np.mod(mp_lats,np.pi/2.0), symb_sizes=5000*seg_lengths, field=field, cmap=cmap, basemap_ax=scalar_basemap) junk = lineament.plotlinmap([lin,], map=scalar_basemap, lat_mirror=True, lon_cyc=np.pi) scalar_basemap.drawmeridians(np.degrees(np.linspace(min_lon, max_lon, 7)), labels=[1,0,0,1], linewidth=0.5, color='gray') scalar_basemap.drawparallels(np.degrees(np.linspace(min_lat, max_lat, 7)), labels=[1,0,0,1], linewidth=0.5, color='gray') scalar_basemap.drawmapboundary()
def test_scalar_grid(min_lon=0.0, max_lon=np.pi, min_lat=-np.pi/2.0, max_lat=np.pi/2.0,\ nlats=181, nlons=181, field='tens', cmap=plt.cm.gray_r): #{{{ satfile = "input/ConvectingEuropa_GlobalDiurnalNSR.ssrun" europa = ss.Satellite(open(satfile, 'r')) NSR = ss.StressCalc([ ss.NSR(europa), ]) the_fig = plt.figure(figsize=(10, 10)) map_ax = the_fig.add_subplot(1, 1, 1) map_ax.set_title("Rasterized scalar stress field (%s)" % (field, )) scalar_basemap = basemap.Basemap(llcrnrlon = np.degrees(min_lon),\ llcrnrlat = np.degrees(min_lat),\ urcrnrlon = np.degrees(max_lon),\ urcrnrlat = np.degrees(max_lat),\ ax = map_ax) scalar_grid(stresscalc=NSR, nlons=nlons, nlats=nlats, min_lon=min_lon, max_lon=max_lon, min_lat=min_lat, max_lat=max_lat,\ field=field, cmap=cmap, basemap_ax=scalar_basemap) scalar_basemap.drawmeridians(np.degrees(np.linspace(min_lon, max_lon, 7)), labels=[1, 0, 0, 1], linewidth=0.5, color='gray') scalar_basemap.drawparallels(np.degrees(np.linspace(min_lat, max_lat, 7)), labels=[1, 0, 0, 1], linewidth=0.5, color='gray') scalar_basemap.drawmapboundary()
def main(): usage = "usage: %prog [options] satfile gridfile outfile" description = __doc__ op = OptionParser(usage) (options, args) = op.parse_args() # Do a (very) little error checking on the arguments: if len(args) != 3: op.error("incorrect number of arguments") # The satfile defines the satellite and forcings it is subject to: satfile = open(args[0], 'r') the_sat = ss.Satellite(satfile) satfile.close() # The gridfile defines the scope and resolution of the calculation: # Note here that we're actually storing information about the satellite in # two places: once in the Grid, and once in the StressDef objects that make # up the StressCalc object. This is probably bad - since one could twiddle # with the parameters on one place, and not the other, and end up getting # apparently bogus output. Be careful. gridfile = open(args[1], 'r') the_grid = Grid(gridfile, satellite=the_sat) gridfile.close() the_stresscalc = ss.StressCalc([ss.NSR(the_sat), ss.Diurnal(the_sat)]) the_gridcalc = GridCalc(the_grid, the_stresscalc) the_gridcalc.write_netcdf(args[2])
def test_vector_grid(plot_tens=True, plot_comp=True, plot_greater=True, plot_lesser=True, min_lon=0.0, max_lon=np.pi, nlons=13, min_lat=-np.pi/2.0, max_lat=np.pi/2.0, nlats=13, t=0.0): #{{{ """ An attempt to exercise the above routines... """ satfile="input/ConvectingEuropa_GlobalDiurnalNSR.ssrun" europa = ss.Satellite(open(satfile,'r')) NSR = ss.StressCalc([ss.NSR(europa),]) grid_min_lon = min_lon grid_max_lon = max_lon grid_min_lat = min_lat grid_max_lat = max_lat vector_grid_nlons = nlons vector_grid_nlats = nlats # Lon/Lat locations to plot the principal components: vector_grid_lons = np.linspace(grid_min_lon, grid_max_lon, vector_grid_nlons) vector_grid_lats = np.linspace(grid_min_lat, grid_max_lat, vector_grid_nlats) vector_mesh_lons, vector_mesh_lats = np.meshgrid(vector_grid_lons, vector_grid_lats) vector_mesh_lons = np.ravel(vector_mesh_lons) vector_mesh_lats = np.ravel(vector_mesh_lats) vector_grid_fig = plt.figure(figsize=(10,10)) vector_grid_ax = vector_grid_fig.add_subplot(1,1,1) vector_grid_ax.set_title("Regularly gridded vectors") vector_grid_basemap = basemap.Basemap(llcrnrlon = np.degrees(grid_min_lon),\ llcrnrlat = np.degrees(grid_min_lat),\ urcrnrlon = np.degrees(grid_max_lon),\ urcrnrlat = np.degrees(grid_max_lat),\ ax = vector_grid_ax) vector_points(stresscalc=NSR, lons=vector_mesh_lons, lats=vector_mesh_lats, time_t=t,\ plot_greater=plot_greater, plot_lesser=plot_lesser,\ plot_comp=plot_comp, plot_tens=plot_tens, basemap_ax=vector_grid_basemap) vector_grid_basemap.drawmeridians(np.degrees(vector_grid_lons), labels=[1,0,0,1], linewidth=0.5, color='gray') vector_grid_basemap.drawparallels(np.degrees(vector_grid_lats), labels=[1,0,0,1], linewidth=0.5, color='gray') vector_grid_basemap.drawmapboundary()
def lingen_nsr_library(nlats=36): #{{{ """ Create a regularaly spaced "grid" of synthetic NSR lineaments, for use in visualizing the expected NSR trajectories, and in fast fitting of lineaments to the stress field. """ import satstress satfile = "input/ConvectingEuropa_GlobalDiurnalNSR.ssrun" europa = satstress.Satellite(open(satfile,'r')) NSR = satstress.StressCalc([satstress.NSR(europa),]) linlist = [] for lat in linspace(0,pi/2,nlats+2)[1:-1]: linlist.append(lingen_nsr(NSR, init_lon=0.0, init_lat=lat, max_length=2*pi, prop_dir='both')) # Now mirror and shift that set of regular lineaments to cover the surface entirely: linlist += [Lineament(lons=lin.lons, lats=-lin.lats, stresscalc=lin.stresscalc) for lin in linlist] linlist += [Lineament(lons=lin.lons+pi, lats=lin.lats, stresscalc=lin.stresscalc) for lin in linlist] return linlist
def test_vector_lin(lin, t=0.0, w_stress=False, w_length=False, scale=5e7, plot_tens=True, plot_comp=False, plot_greater=True, plot_lesser=False): #{{{ import lineament satfile="input/ConvectingEuropa_GlobalDiurnalNSR.ssrun" europa = ss.Satellite(open(satfile,'r')) NSR = ss.StressCalc([ss.NSR(europa),]) best_b = lin.best_fit()[1] mp_lons, mp_lats = lin.seg_midpoints() if w_length is True: scale_arr = len(mp_lons)*lin.seg_lengths()/lin.length else: scale_arr = np.ones(np.shape(mp_lons)) min_lat = 0 max_lat = np.pi/2.0 min_lon = 0.0 max_lon = np.pi vector_lin_fig = plt.figure() vector_lin_ax = vector_lin_fig.add_subplot(1,1,1) vector_lin_ax.set_title("Vectors at arbitrary locations (e.g. along a feature)") vector_lin_basemap = basemap.Basemap(llcrnrlon = np.degrees(min_lon),\ llcrnrlat = np.degrees(min_lat),\ urcrnrlon = np.degrees(max_lon),\ urcrnrlat = np.degrees(max_lat),\ ax = vector_lin_ax) junk = lineament.plotlinmap([lin,], map=vector_lin_basemap, lat_mirror=True, lon_cyc=np.pi) vector_lin_basemap.drawmeridians(np.degrees(np.linspace(min_lon, max_lon,13)), labels=[1,0,0,1], linewidth=0.5, color='gray') vector_lin_basemap.drawparallels(np.degrees(np.linspace(min_lat, max_lat, 7)), labels=[1,0,0,1], linewidth=0.5, color='gray') vector_lin_basemap.drawmapboundary() vector_points(stresscalc=NSR, lons=np.mod(mp_lons,np.pi), lats=mp_lats, time_t=0.0, lonshift=best_b,\ plot_tens=plot_tens, plot_greater=plot_greater, plot_comp=plot_comp, plot_lesser=plot_lesser, basemap_ax=vector_lin_basemap, scale=scale, scale_arr=scale_arr, w_stress=w_stress)
def write_netcdf(self, outfile): """ Output a netCDF file containing the results of the calculation specified by the GridCalc object. Each stress field encapsulated in the GridCalc object will be output within the netCDF file as three data fields, one for each of the stress tensor components L{Ttt}_NAME, L{Tpt}_NAME, L{Tpp}_NAME, where NAME is the name of the L{StressDef} object (e.g. L{Diurnal} or L{NSR}). Writing out the calculation results causes the calculation to take place. No mechanism for performing the calculation and retaining it in memory for manipulation is currently provided. """ # Create a netCDF file object to stick the calculation results in: nc_out = netCDF3.Dataset(outfile, 'w') # Set metadata fields of nc_out appropriate to the calculation at hand. nc_out.description = "satstress calculation on a regular grid. All parameter units are SI (meters-kilograms-seconds)" nc_out.history = """Created: %s using the satstress python package: http://code.google.com/p/satstress""" % ( time.ctime(time.time())) nc_out.Conventions = __NETCDF_CONVENTIONS__ ######################################################################## # Independent (input) parameters for the run: ######################################################################## nc_out.grid_id = self.grid.grid_id nc_out.system_id = self.grid.satellite.system_id nc_out.planet_mass = self.grid.satellite.planet_mass nc_out.orbit_eccentricity = self.grid.satellite.orbit_eccentricity nc_out.orbit_semimajor_axis = self.grid.satellite.orbit_semimajor_axis nc_out.layer_id_0 = self.grid.satellite.layers[0].layer_id nc_out.density_0 = self.grid.satellite.layers[0].density nc_out.lame_mu_0 = self.grid.satellite.layers[0].lame_mu nc_out.lame_lambda_0 = self.grid.satellite.layers[0].lame_lambda nc_out.thickness_0 = self.grid.satellite.layers[0].thickness nc_out.viscosity_0 = self.grid.satellite.layers[0].viscosity nc_out.tensile_str_0 = self.grid.satellite.layers[0].tensile_str nc_out.layer_id_1 = self.grid.satellite.layers[1].layer_id nc_out.density_1 = self.grid.satellite.layers[1].density nc_out.lame_mu_1 = self.grid.satellite.layers[1].lame_mu nc_out.lame_lambda_1 = self.grid.satellite.layers[1].lame_lambda nc_out.thickness_1 = self.grid.satellite.layers[1].thickness nc_out.viscosity_1 = self.grid.satellite.layers[1].viscosity nc_out.tensile_str_1 = self.grid.satellite.layers[1].tensile_str nc_out.layer_id_2 = self.grid.satellite.layers[2].layer_id nc_out.density_2 = self.grid.satellite.layers[2].density nc_out.lame_mu_2 = self.grid.satellite.layers[2].lame_mu nc_out.lame_lambda_2 = self.grid.satellite.layers[2].lame_lambda nc_out.thickness_2 = self.grid.satellite.layers[2].thickness nc_out.viscosity_2 = self.grid.satellite.layers[2].viscosity nc_out.tensile_str_2 = self.grid.satellite.layers[2].tensile_str nc_out.layer_id_3 = self.grid.satellite.layers[3].layer_id nc_out.density_3 = self.grid.satellite.layers[3].density nc_out.lame_mu_3 = self.grid.satellite.layers[3].lame_mu nc_out.lame_lambda_3 = self.grid.satellite.layers[3].lame_lambda nc_out.thickness_3 = self.grid.satellite.layers[3].thickness nc_out.viscosity_3 = self.grid.satellite.layers[3].viscosity nc_out.tensile_str_3 = self.grid.satellite.layers[3].tensile_str ######################################################################## # A selection of dependent (output) parameters for the run. ######################################################################## nc_out.satellite_radius = self.grid.satellite.radius() nc_out.satellite_mass = self.grid.satellite.mass() nc_out.satellite_density = self.grid.satellite.density() nc_out.satellite_surface_gravity = self.grid.satellite.surface_gravity( ) nc_out.satellite_orbit_period = self.grid.satellite.orbit_period() ######################################################################## # What about Frequency dependent Parameters? ######################################################################## # There are a variety of interesting frequency-dependent parameters # that we ought to really output as well (delta, and the complex Love # numbers, Lame parameters...) for reference, but they'll all depend on # exactly which slice (for instance) in NSR we're looking at, so the # right place to put this meta-data isn't really in the global section # it should be associated with the stress variables themselves. # # It seems that the right way to do this is to define several 1-d # variables that are not coordinate variables (that is, they don't # correspond to one of the dimensions, unlike latitude, or longitude) # e.g.: # nc_out.createVariable('nsr_delta_upper', self.grid.nsr_period_num, ('nsr_period')) # nc_out.createVariable('nsr_lame_mu_twiddle', self.grid.nsr_period_num, ('nsr_period')) ######################################################################## # A few parameters pertaining to the web-interface only: ######################################################################## # TODO nc_out.ssweb_run_id = "" nc_out.ssweb_username = "" nc_out.ssweb_ip_address = "" ######################################################################## # Specify the size and shape of the output datacube. ######################################################################## # LATITUDE: nc_out.createDimension('latitude', self.grid.lat_num) lats = nc_out.createVariable('latitude', 'f4', ('latitude', )) lats.units = "degrees_north" lats.long_name = "latitude" lats[:] = numpy.linspace(self.grid.lat_min, self.grid.lat_max, self.grid.lat_num) # LONGITUDE: nc_out.createDimension('longitude', self.grid.lon_num) lons = nc_out.createVariable('longitude', 'f4', ('longitude', )) lons.units = "degrees_east" lons.long_name = "longitude" lons[:] = numpy.linspace(self.grid.lon_min, self.grid.lon_max, self.grid.lon_num) # NSR_PERIOD nc_out.createDimension('nsr_period', self.grid.nsr_period_num) nsr_periods = nc_out.createVariable('nsr_period', 'f4', ('nsr_period', )) nsr_periods.units = "seconds" nsr_periods.long_name = "NSR period" nsr_periods[:] = numpy.logspace(numpy.log10(self.grid.nsr_period_min), numpy.log10(self.grid.nsr_period_max), self.grid.nsr_period_num) # TIME: # Check to see what kind of units we're using for time, and name the # variables and their units appropriately if self.grid.orbit_min is None: nc_out.createDimension('time', self.grid.time_num) times = nc_out.createVariable('time', 'f4', ('time', )) times.units = "seconds" times.long_name = "time after periapse" times[:] = numpy.linspace(self.grid.time_min, self.grid.time_max, self.grid.time_num) else: nc_out.createDimension('time', self.grid.orbit_num) times = nc_out.createVariable('time', 'f4', ('time', )) times.units = "degrees" times.long_name = "degrees after periapse" times[:] = numpy.linspace(self.grid.orbit_min, self.grid.orbit_max, self.grid.orbit_num) # At this point, we should have all the netCDF dimensions and their # corresponding coordinate variables created (latitutde, longitude, # time/orbit, nsr_period), but we still haven't created the data # variables, which will ultimately hold the results of our stress # calculation, and which depend on the aforedefined dimensions # DIURNAL: Ttt_Diurnal = nc_out.createVariable('Ttt_Diurnal', 'f4', ( 'time', 'latitude', 'longitude', )) Ttt_Diurnal.units = "Pa" Ttt_Diurnal.long_name = "north-south component of Diurnal eccentricity stresses" Tpt_Diurnal = nc_out.createVariable('Tpt_Diurnal', 'f4', ( 'time', 'latitude', 'longitude', )) Tpt_Diurnal.units = "Pa" Tpt_Diurnal.long_name = "shear component of Diurnal eccentricity stresses" Tpp_Diurnal = nc_out.createVariable('Tpp_Diurnal', 'f4', ( 'time', 'latitude', 'longitude', )) Tpp_Diurnal.units = "Pa" Tpp_Diurnal.long_name = "east-west component of Diurnal eccentricity stresses" # NSR: Ttt_NSR = nc_out.createVariable('Ttt_NSR', 'f4', ( 'nsr_period', 'latitude', 'longitude', )) Ttt_NSR.units = "Pa" Ttt_NSR.long_name = "north-south component of NSR stresses" Tpt_NSR = nc_out.createVariable('Tpt_NSR', 'f4', ( 'nsr_period', 'latitude', 'longitude', )) Tpt_NSR.units = "Pa" Tpt_NSR.long_name = "shear component of NSR stresses" Tpp_NSR = nc_out.createVariable('Tpp_NSR', 'f4', ( 'nsr_period', 'latitude', 'longitude', )) Tpp_NSR.units = "Pa" Tpp_NSR.long_name = "east-west component of NSR stresses" # Get the StressDef objects corresponding to Diurnal and NSR stresses: for stress in self.stresscalc.stresses: if stress.__name__ is 'Diurnal': diurnal_stress = ss.StressCalc([ stress, ]) if stress.__name__ is 'NSR': nsr_stress = ss.StressCalc([ stress, ]) # Loop over the time variable, doing diurnal calculations over an orbit for t in range(len(times[:])): # We need some kind of progress update, and we need to make sure that # we have a representation of the time coordinate in seconds, because # that's what the satstress library expects - even if we're ultimately # communicating time to the user in terms of "degrees after periapse" if self.grid.orbit_min is None: time_sec = times[t] else: time_sec = diurnal_stress.stresses[0].satellite.orbit_period( ) * (times[t] / 360.0) print "Calculating Diurnal stresses at", times[t], times.long_name for lon in range(len(lons[:])): for lat in range(len(lats[:])): Tau_D = diurnal_stress.tensor(theta = scipy.radians(90.0-lats[lat]),\ phi = scipy.radians(lons[lon]),\ t = time_sec ) nc_out.variables['Ttt_Diurnal'][t, lat, lon] = Tau_D[0, 0] nc_out.variables['Tpt_Diurnal'][t, lat, lon] = Tau_D[1, 0] nc_out.variables['Tpp_Diurnal'][t, lat, lon] = Tau_D[1, 1] # Make sure everything gets written out to the file. nc_out.sync() # Change the satellite's eccentricity to zero to exclude the Diurnal # stresses for the purposes of calculating the NSR stresses: nsr_stress.stresses[0].satellite.orbit_eccentricity = 0.0 # Loop over all the prescribed values of NSR_PERIOD, and do the NSR stress calculation # at each point on the surface. for p_nsr in range(len(nsr_periods[:])): # Adjust the properties of the Satellite and StressDef objects # for the nsr_period being considered: new_sat = nsr_stress.stresses[0].satellite new_sat.nsr_period = nsr_periods[p_nsr] nsr_stress = ss.StressCalc([ ss.NSR(new_sat), ]) print "Calculating NSR stresses for Pnsr = %g %s" % ( nsr_periods[p_nsr], nsr_periods.units, ) for lon in range(len(lons[:])): for lat in range(len(lats[:])): Tau_N = nsr_stress.tensor(theta = scipy.radians(90-lats[lat]),\ phi = scipy.radians(lons[lon]),\ t = 0 ) nc_out.variables['Ttt_NSR'][p_nsr, lat, lon] = Tau_N[0, 0] nc_out.variables['Tpt_NSR'][p_nsr, lat, lon] = Tau_N[1, 0] nc_out.variables['Tpp_NSR'][p_nsr, lat, lon] = Tau_N[1, 1] # Make sure everything gets written out to the file. nc_out.sync()