def test_post_files(request): if not request.method == "POST": return HttpResponseBadRequest('expecting post requests!') else: with open('%s/tmp.gpmlz' % settings.MEDIA_ROOT, 'wb+') as destination: for chunk in request.FILES['file1'].chunks(): destination.write(chunk) with open('%s/tmp.rot' % settings.MEDIA_ROOT, 'wb+') as destination: for chunk in request.FILES['file2'].chunks(): destination.write(chunk) filename = 'reconstruct_to_birth_time.gpmlz' rotation_model = pygplates.RotationModel('%s/tmp.rot' % settings.MEDIA_ROOT) features = pygplates.FeatureCollection('%s/tmp.gpmlz' % settings.MEDIA_ROOT) reconstructed_features = reconstruct_to_birth_time( features, rotation_model) tmp = pygplates.FeatureCollection(reconstructed_features) tmp.write('%s/%s' % (settings.MEDIA_ROOT, filename)) f = StringIO( file('%s/%s' % (settings.MEDIA_ROOT, filename), "rb").read()) response = HttpResponse(f, content_type='application/gpmlz') response['Content-Disposition'] = 'attachment; filename=%s' % filename return response
def masking_job(reconstruction_time, COBterrane_file, input_rotation_filenames, grdspace, grd_output_dir, output_gridfile_template='seafloor_age_'): rotation_model = pygplates.RotationModel(input_rotation_filenames) print('Masking for time {:0.2f} Ma'.format(reconstruction_time)) #mask = pt.get_merged_cob_terrane_raster(COBterrane_file, rotation_model, reconstruction_time, # grdspace) maskX, maskY, mask = load_netcdf('{0}/masks/mask_{1}Ma.nc'.format( grd_output_dir, reconstruction_time)) ds = xr.open_dataset('{0}/unmasked/{1}{2}Ma.nc'.format( grd_output_dir, output_gridfile_template, reconstruction_time)) # workaround for a bug in older versions of xarray, where masking array cannot be applied directly to data array #ds['z'][mask==1] = np.nan z_array = ds['z'].data z_array[mask == 1] = np.nan ds['z'].data = z_array ds.to_netcdf('{0}/masked/{1}mask_{2}Ma.nc'.format( grd_output_dir, output_gridfile_template, reconstruction_time), format='NETCDF4_CLASSIC') ds.close() return
def get_deposit_candidates(): polygon_points = get_region_of_interest_polygon().values.flatten() mesh_points = get_mesh_points(polygon_points) #let's find plate id for the mesh points static_polygons = pygplates.FeatureCollection( parameters['static_polygons_file']) rotation_model = pygplates.RotationModel( get_files(parameters['rotation_files'])) mesh_plate_ids = get_plate_id(mesh_points.lon.tolist(), mesh_points.lat.tolist(), static_polygons, rotation_model) mesh_points['plate_id'] = mesh_plate_ids deposit_candidates = [] start_time = parameters["time"]["start"] end_time = parameters["time"]["end"] time_step = parameters["time"]["step"] for t in range(start_time, end_time + 1, time_step): for index, p in mesh_points.iterrows(): deposit_candidates.append([p['lon'], p['lat'], t, p['plate_id']]) deposit_candidates = pd.DataFrame( deposit_candidates, columns=['lon', 'lat', 'age', 'plate_id']) deposit_candidates = deposit_candidates.astype({ "plate_id": int, "age": int }) return deposit_candidates
def __init__(self, grid_list_filename, static_polygon_filename, rotation_filenames, longitude, latitude, age=None): """ Load dynamic topography grid filenames and associated ages from grid list file 'grid_list_filename'. The present day location ('longitude' / 'latitude' in degrees) is also assigned a plate ID using the static polygons. """ self.location = pygplates.PointOnSphere((latitude, longitude)) self.age = age self.grids = TimeDependentGrid(grid_list_filename) self.rotation_model = pygplates.RotationModel(rotation_filenames) # Find the plate ID of the static polygon containing the location (or zero if not in any plates). plate_partitioner = pygplates.PlatePartitioner(static_polygon_filename, self.rotation_model) partitioning_plate = plate_partitioner.partition_point(self.location) if partitioning_plate: self.reconstruction_plate_id = partitioning_plate.get_feature().get_reconstruction_plate_id() else: self.reconstruction_plate_id = 0 # Use the age of the containing static polygon if location is None (ie, outside age grid). if self.age is None: if partitioning_plate: self.age, _ = partitioning_plate.get_feature().get_valid_time() else: self.age = 0.0
def __init__(self, grid_list_filename, static_polygon_filename, rotation_filenames, longitude, latitude, age=None): """ Load dynamic topography grid filenames and associated ages from grid list file 'grid_list_filename'. Parameters ---------- grid_list_filename : str The filename of the grid list file. static_polygon_filename : str The filename of the static polygons file. rotation_filenames : list of str The list of rotation filenames. longitude : float Longitude of the ocean point location. latitude : float Latitude of the ocean point location. age : float, optional The age of the crust that the point location is on. If not specified then the appearance age of the static polygon containing the point is used. Notes ----- Each row in the grid list file should contain two columns. First column containing filename (relative to directory of list file) of a dynamic topography grid at a particular time. Second column containing associated time (in Ma). The present day location ('longitude' / 'latitude' in degrees) is also assigned a plate ID using the static polygons, and the rotations are used to reconstruct the location when sampling the grids at a reconstructed time. """ self.latitude = latitude self.longitude = longitude self.location = pygplates.PointOnSphere((latitude, longitude)) self.age = age self.grids = TimeDependentGrid(grid_list_filename) self.rotation_model = pygplates.RotationModel(rotation_filenames) # Find the plate ID of the static polygon containing the location (or zero if not in any plates). plate_partitioner = pygplates.PlatePartitioner(static_polygon_filename, self.rotation_model) partitioning_plate = plate_partitioner.partition_point(self.location) if partitioning_plate: self.reconstruction_plate_id = partitioning_plate.get_feature( ).get_reconstruction_plate_id() else: self.reconstruction_plate_id = 0 # Use the age of the containing static polygon if location is None (ie, outside age grid). if self.age is None: if partitioning_plate: self.age, _ = partitioning_plate.get_feature().get_valid_time() else: self.age = 0.0
def resolve_topologies( rotation_features_or_model, topology_features, time, output_filename_prefix, output_filename_extension, transform_segment_deviation_in_radians=separate_ridge_transform_segments. DEFAULT_TRANSFORM_SEGMENT_DEVIATION_RADIANS): """ Resolves topologies at specified time and saves (to separate files) the resolved topologies, and their boundary sections as subduction zones, mid-ocean ridges (ridge/transform) and others (not subduction zones or mid-ocean ridges). rotation_features_or_model: Rotation model or feature collection(s), or list of features, or filename(s). topology_features: Topology feature collection(s), or list of features, or filename(s) or any combination of those. time: Reconstruction time to resolved topologies. transform_segment_deviation_in_radians: How much a mid-ocean ridge segment can deviate from the stage pole before it's considered a transform segment (in radians). Writes output files containing the following features... - resolved topology features (topological plates and networks) - ridge and transform boundary sections (resolved features) - ridge boundary sections (resolved features) - transform boundary sections (resolved features) - subduction boundary sections (resolved features) - left subduction boundary sections (resolved features) - right subduction boundary sections (resolved features) - other boundary sections (resolved features) that are not subduction zones or mid-ocean ridges (ridge/transform) """ # Turn rotation data into a RotationModel (if not already). rotation_model = pygplates.RotationModel(rotation_features_or_model) # Get topology features (could include filenames). topology_features = pygplates.FeaturesFunctionArgument( topology_features).get_features() # Resolve our topological plate polygons (and deforming networks) to the current 'time'. # We generate both the resolved topology boundaries and the boundary sections between them. (resolved_topology_features, ridge_transform_boundary_section_features, ridge_boundary_section_features, transform_boundary_section_features, subduction_boundary_section_features, left_subduction_boundary_section_features, right_subduction_boundary_section_features, other_boundary_section_features) = resolve_topologies_into_features( rotation_model, topology_features, time, transform_segment_deviation_in_radians) # Write each list of features to a separate file. _write_resolved_topologies( time, output_filename_prefix, output_filename_extension, resolved_topology_features, ridge_transform_boundary_section_features, ridge_boundary_section_features, transform_boundary_section_features, subduction_boundary_section_features, left_subduction_boundary_section_features, right_subduction_boundary_section_features, other_boundary_section_features)
def paleolithology(request): anchor_plate_id = request.GET.get('pid', 0) time = request.GET.get('time', 0) model = request.GET.get('model', settings.MODEL_DEFAULT) model_dict = get_reconstruction_model_dict(model) rotation_model = pygplates.RotationModel([ str('%s/%s/%s' % (settings.MODEL_STORE_DIR, model, rot_file)) for rot_file in model_dict['RotationFile'] ]) paleolithology_datafile = '%s/boucot_paleolithology_combined.shp' % settings.PALEO_STORE_DIR static_polygons_filename = str( '%s/%s/%s' % (settings.MODEL_STORE_DIR, model, model_dict['StaticPolygons'])) #select points based on age before doing plate id assignment - should be quicker?? paleolithology_points = pygplates.FeatureCollection( paleolithology_datafile) valid_points = [] for point in paleolithology_points: if point.get_valid_time()[0] > float( time) and point.get_valid_time()[1] <= float(time): valid_points.append(point) print(valid_points) assigned_features = pygplates.partition_into_plates( static_polygons_filename, rotation_model, valid_points, properties_to_copy=[ pygplates.PartitionProperty.reconstruction_plate_id ], partition_method=pygplates.PartitionMethod.most_overlapping_plate) reconstructed_paleolithology_points = [] pygplates.reconstruct(assigned_features, rotation_model, reconstructed_paleolithology_points, float(time), anchor_plate_id=anchor_plate_id) ret = write_json_reconstructed_point_features( reconstructed_paleolithology_points, attributes=[('LithCode', 'string'), ('Period', 'string')]) #add header for CORS #http://www.html5rocks.com/en/tutorials/cors/ response = HttpResponse(ret, content_type='application/json') #TODO: #The "*" makes the service wide open to anyone. We should implement access control when time comes. response['Access-Control-Allow-Origin'] = '*' return response
def get_topological_boundaries(request): """ http GET request to retrieve reconstructed topological plate polygons **usage** <http-address-to-gws>/topology/plate_boundaries/time=\ *reconstruction_time*\&model=\ *reconstruction_model* **parameters:** *time* : time for reconstruction [default=0] *model* : name for reconstruction model [defaults to default model from web service settings] **returns:** json containing reconstructed plate boundary features """ time = request.GET.get('time', 0) model = request.GET.get('model', settings.MODEL_DEFAULT) model_dict = get_reconstruction_model_dict(model) features = [] rotation_model = pygplates.RotationModel([ str('%s/%s/%s' % (settings.MODEL_STORE_DIR, model, rot_file)) for rot_file in model_dict['RotationFile'] ]) # need to handle cases where topologies are in one file, and where they are spread across # multiple files topology_features = pygplates.FeatureCollection() if type(model_dict['PlatePolygons']) is list: for file in model_dict['PlatePolygons']: fullfile = str('%s/%s/%s' % (settings.MODEL_STORE_DIR, model, file)) topology_feature = pygplates.FeatureCollection(fullfile) topology_features.add(topology_feature) else: topology_features = pygplates.FeatureCollection( str('%s/%s/%s' % (settings.MODEL_STORE_DIR, model, model_dict['PlatePolygons']))) resolved_polygons = [] shared_boundary_sections = [] pygplates.resolve_topologies(topology_features, rotation_model, resolved_polygons, float(time), shared_boundary_sections) data = wrap_plate_boundaries(shared_boundary_sections, 0.) print('here') ret = json.dumps(pretty_floats(data)) response = HttpResponse(ret, content_type='application/json') #TODO: response['Access-Control-Allow-Origin'] = '*' return response
def calculate_velocities_over_time(output_filename_prefix, output_filename_extension, rotation_filenames, reconstructable_filenames, threshold_sampling_distance_radians, time_young, time_old, time_increment, velocity_delta_time=1.0, anchor_plate_id=0): if time_increment <= 0: print('The time increment "{0}" is not positive and non-zero.'.format( time_increment), file=sys.stderr) return if time_young > time_old: print('The young time {0} is older (larger) than the old time {1}.'. format(time_young, time_old), file=sys.stderr) return rotation_model = pygplates.RotationModel(rotation_filenames) # Read/parse the reconstructable features once so we're not doing at each time iteration. reconstructable_features = [ pygplates.FeatureCollection(reconstructable_filename) for reconstructable_filename in reconstructable_filenames ] # Iterate over the time range. time = time_young while time <= pygplates.GeoTimeInstant(time_old): print('Time {0}'.format(time)) # Returns a list of tesselated subduction zone points and associated convergence parameters # to write to the output file for the current 'time'. output_data = calculate_velocities( rotation_model, reconstructable_features, threshold_sampling_distance_radians, time, velocity_delta_time, anchor_plate_id) if output_data: output_filename = '{0}_{1:0.2f}.{2}'.format( output_filename_prefix, time, output_filename_extension) write_output_file(output_filename, output_data) # Increment the time further into the past. time += time_increment return 0 # Success
def test_post(request): if not request.method == "POST": return HttpResponseBadRequest('expecting post requests!') else: #print request.POST json_feature_collection = json.loads(request.body) model = request.GET.get('model', settings.MODEL_DEFAULT) features = [] for json_feature in json_feature_collection['features']: feature = pygplates.Feature() point = json_feature['geometry']['coordinates'] feature.set_geometry(pygplates.PointOnSphere(point[1], point[0])) feature.set_valid_time(json_feature['properties']['age'], 0) features.append(feature) model_dict = get_reconstruction_model_dict(model) rotation_model = pygplates.RotationModel([ str('%s/%s/%s' % (settings.MODEL_STORE_DIR, model, rot_file)) for rot_file in model_dict['RotationFile'] ]) static_polygons_filename = str( '%s/%s/%s' % (settings.MODEL_STORE_DIR, model, model_dict['StaticPolygons'])) # assign plate-ids to points using static polygons assigned_point_features = pygplates.partition_into_plates( static_polygons_filename, rotation_model, features, properties_to_copy=[ pygplates.PartitionProperty.reconstruction_plate_id ]) feature_collection = pygplates.FeatureCollection( assigned_point_features) reconstructed_features = reconstruct_to_birth_time( feature_collection, rotation_model) # prepare the response to be returned ret = '{"coordinates":[' for g in reconstructed_features: ret += '[{0:5.2f},{1:5.2f}],'.format( g.get_geometry().to_lat_lon()[1], g.get_geometry().to_lat_lon()[0]) ret = ret[0:-1] ret += ']}' return HttpResponse(ret, content_type='application/json')
def __init__(self, rotation_filenames, topology_filenames, geologic_zero, nseeds=1000, nneighbours=3, delta_time=1.): """ A class for importing surface velocities from pygplates. Each time surface velocity points are generated for [nseeds] of equidistantial points at the surface. With these points a cKDTree obect is generated each time, which will be used to interpolate onto required grid points. Interpolation is a weighted average of [nneighbours] closest points, unless the closest points is closer than ~numerical zero. input: rotation_filenames: list of rotation files topology_filenames: list of dynamic polygon files geologic_zero: what is the oldest geologic time available in this model nseeds: number of seed points to generate nneighbours: when interpolating between the seed points and mesh points, how many neighboring points should be used delta_time: how many million years should it take before we read in plate velocities again (is passed on to pygplates for time averaging too) """ # Rotation model(s) self.rotation_model = pygplates.RotationModel(rotation_filenames) if nneighbours < 2: raise ValueError('nneighbours should be at least 2') else: self.nneighbours = nneighbours # Topological plate polygon feature(s). self.topology_features = [] for fname in topology_filenames: for f in pygplates.FeatureCollection(fname): self.topology_features.append(f) # geologic_zero is the same as model_time=0 self.geologic_zero = geologic_zero # time window for velocity interpolations self.delta_time = delta_time # NB: Not sure if we really need to keep seeds at this stage self.seeds = self.__fibonacci_sphere(samples=int(nseeds)) # self.velocity_domain_features = self.__make_GPML_velocity_feature( self.seeds) # last reconstruction time self.reconstruction_time = None # Flag to know when to recalculate surface velocities. self.recalculation_flg = False
def plot_velocities(self, m): delta_time = 5. Xnodes = np.arange(-180, 180, 5) Ynodes = np.arange(-90, 90, 5) Xg, Yg = np.meshgrid(Xnodes, Ynodes) Xg = Xg.flatten() Yg = Yg.flatten() velocity_domain_features = velocity_utils.make_GPML_velocity_feature( Xg, Yg) # Load one or more rotation files into a rotation model. rotation_model = pygplates.RotationModel(rotation_filenames) # Load the topological plate polygon features. topology_features = [] for fname in topology_filenames: for f in pygplates.FeatureCollection(fname): topology_features.append(f) # Call the function we created above to get the velocities all_velocities = velocity_utils.Get_Plate_Velocities( velocity_domain_features, topology_features, rotation_model, self.reconstruction_time, delta_time, 'vector_comp') uu = [] vv = [] for vel in all_velocities: if not hasattr(vel, 'get_y'): uu.append(vel[1]) vv.append(vel[0]) else: uu.append(vel.get_y()) vv.append(vel.get_x()) u = np.asarray([uu]).reshape((Ynodes.shape[0], Xnodes.shape[0])) v = np.asarray([vv]).reshape((Ynodes.shape[0], Xnodes.shape[0])) # compute native x,y coordinates of grid. x, y = m(Xg, Yg) uproj, vproj, xx, yy = m.transform_vector(u, v, Xnodes, Ynodes, 15, 15, returnxy=True, masked=True) # now plot. Q = m.quiver(xx, yy, uproj, vproj, scale=1000, color='grey') # make quiver key. qk = plt.quiverkey(Q, 0.95, 1.05, 50, '50 mm/yr', labelpos='W')
def subduction(request): if not request.method == "POST": return HttpResponseBadRequest('expecting post requests!') else: #print request.POST json_feature_collection = json.loads(request.body) model = request.GET.get('model', settings.MODEL_DEFAULT) features = [] for json_feature in json_feature_collection['features']: feature = pygplates.Feature() point = json_feature['geometry']['coordinates'] feature.set_geometry(pygplates.PointOnSphere(point[1], point[0])) feature.set_valid_time(json_feature['properties']['age'], 0) features.append(feature) model_dict = get_reconstruction_model_dict(model) rotation_model = pygplates.RotationModel([ str('%s/%s/%s' % (settings.MODEL_STORE_DIR, model, rot_file)) for rot_file in model_dict['RotationFile'] ]) static_polygons_filename = str( '%s/%s/%s' % (settings.MODEL_STORE_DIR, model, model_dict['StaticPolygons'])) # assign plate-ids to points using static polygons assigned_point_features = pygplates.partition_into_plates( static_polygons_filename, rotation_model, features, properties_to_copy=[ pygplates.PartitionProperty.reconstruction_plate_id ]) seed_point_features = pygplates.FeatureCollection( assigned_point_features) df_OreDepositBirthTimeStats = subduction_parameters( seed_point_features, rotation_model) html_table = df_OreDepositBirthTimeStats.to_html(index=False) return render(request, 'list_template.html', {'html_table': html_table})
def get_isochrons_for_ridge_snapshot(topology_features, rotation_filename, out_dir, ridge_time, time_step, youngest_seed_time=0, ridge_sampling=2.): print("... Writing seed points along a ridge") if not os.path.exists(out_dir): os.makedirs(out_dir) rotation_model = pygplates.RotationModel(rotation_filename) oldest_seed_time = ridge_time all_longitudes = [] all_latitudes = [] all_ages = [] # The first step is to generate points along the ridge resolved_topologies = [] shared_boundary_sections = [] pygplates.resolve_topologies(topology_features, rotation_filename, resolved_topologies, oldest_seed_time, shared_boundary_sections) # Previous points are on the MOR, current are moved by one time step off MOR. curr_points = get_mid_ocean_ridges(shared_boundary_sections, rotation_model, oldest_seed_time, time_step, ridge_sampling) # Write out the ridge point born at 'ridge_time' but their position at 'ridge_time - time_step'. mor_point_features = [] for curr_point in curr_points: feature = pygplates.Feature() feature.set_geometry(curr_point) feature.set_valid_time(ridge_time, -999) # delete - time_step mor_point_features.append(feature) pygplates.FeatureCollection(mor_point_features).write( './{:s}/MOR_plus_one_points_{:0.2f}.gmt'.format(out_dir, ridge_time)) # print( "... Finished writing seed points along the mid ocean ridge for {:0.2f} Ma" .format(ridge_time))
def make_masks_job(reconstruction_time, COBterrane_file, input_rotation_filenames, grdspace, grd_output_dir): rotation_model = pygplates.RotationModel(input_rotation_filenames) print('Masking for time {:0.2f} Ma'.format(reconstruction_time)) mask = get_merged_cob_terrane_raster(COBterrane_file, rotation_model, reconstruction_time, grdspace) gridX = np.arange(-180., 180. + grdspace, grdspace) gridY = np.arange(-90., 90. + grdspace, grdspace) #write_netcdf_grid('{0}/masks/mask_{1}Ma.nc'.format(grd_output_dir, reconstruction_time), # gridX, gridY, mask.astype(int)) ds = xr.DataArray(mask, coords=[('y', gridY), ('x', gridX)], name='z') ds.to_netcdf('{0}/masks/mask_{1}Ma.nc'.format(grd_output_dir, reconstruction_time), format='NETCDF4_CLASSIC', encoding={'z': { 'dtype': 'int16' }}) ds.close() return
def reconstruct_points(request): points = request.GET.get('points', None) plate_id = request.GET.get('pid', None) time = request.GET.get('time', None) rotation_model = pygplates.RotationModel( MODEL_DEFAULT+"Seton_etal_ESR2012_2012.1.rot") static_polygons_filename = \ MODEL_DEFAULT+"Seton_etal_ESR2012_StaticPolygons_2012.1.gpmlz" point_features = [] if points: ps = points.split(',') if len(ps)%2==0: for lat,lon in zip(ps[1::2], ps[0::2]): point_feature = pygplates.Feature() point_feature.set_geometry(pygplates.PointOnSphere(float(lat),float(lon))) point_features.append(point_feature) #for f in point_features: # f.set_reconstruction_plate_id(int(plate_id)) assigned_point_features = pygplates.partition_into_plates( static_polygons_filename, rotation_model, point_features, properties_to_copy = [ pygplates.PartitionProperty.reconstruction_plate_id, pygplates.PartitionProperty.valid_time_period]) assigned_point_feature_collection = pygplates.FeatureCollection(assigned_point_features) reconstructed_feature_geometries = [] pygplates.reconstruct(assigned_point_feature_collection, rotation_model, reconstructed_feature_geometries, float(time)) ret='{"coordinates":[' for g in reconstructed_feature_geometries: ret+='[{0:5.2f},{1:5.2f}],'.format( g.get_reconstructed_geometry().to_lat_lon()[1], g.get_reconstructed_geometry().to_lat_lon()[0]) ret=ret[0:-1] ret+=']}' return HttpResponse(ret, content_type='application/json')
def FeatureCollection(model=default_model, layer='rotations', url=default_url, proxy=''): """ function to access gpml data files directly from the gplates-web-service data store and load them into pygplates feature collections. :param model: :param layer: 'rotations', 'coastlines', 'static_polygons', 'plate_polygons' :param url: :param proxy: """ if layer == 'rotations': requested_file = 'request.rot' else: requested_file = 'request.gpmlz' with open(requested_file, 'wb') as handle: r = requests.get('%s/model/get_model_layer/?model=%s&layer=%s' % (url, model, layer), proxies={'http': '%s' % proxy}, stream=True) if r.status_code != 200: error_string = 'Remote request returned with message %s' % r.text raise Exception(error_string) else: for block in r.iter_content(1024): handle.write(block) if layer == 'rotations': result = pygplates.RotationModel('request.rot') else: result = pygplates.FeatureCollection('request.gpmlz') return result
def reconstruct_coastlines(time): shp_path = settings.MODEL_STORE_DIR+'/'+settings.MODEL_DEFAULT+'/coastlines_low_res/Seton_etal_ESR2012_Coastlines_2012.shp' import shapefile sf = shapefile.Reader(shp_path) features = [] for record in sf.shapeRecords(): if record.shape.shapeType != 5: continue for idx in range(len(record.shape.parts)): start_idx = record.shape.parts[idx] end_idx = len(record.shape.points) if idx < (len(record.shape.parts) -1): end_idx = record.shape.parts[idx+1] polygon_feature = pygplates.Feature() points = record.shape.points[start_idx:end_idx] polygon_feature.set_geometry( pygplates.PolygonOnSphere([(lat,lon) for lon, lat in points])) polygon_feature.set_reconstruction_plate_id(int(record.record[0])) features.append(polygon_feature) break feature_collection = pygplates.FeatureCollection(features) reconstructed_polygons = [] model_dict = get_reconstruction_model_dict(settings.MODEL_DEFAULT) rotation_model = pygplates.RotationModel([str('%s/%s/%s' % (settings.MODEL_STORE_DIR,settings.MODEL_DEFAULT,rot_file)) for rot_file in model_dict['RotationFile']]) pygplates.reconstruct( feature_collection, rotation_model, reconstructed_polygons, float(time)) return reconstructed_polygons
def spreading_rates( rotation_features_or_model, topology_features, time, threshold_sampling_distance_radians, spreading_feature_types=None, transform_segment_deviation_in_radians=separate_ridge_transform_segments .DEFAULT_TRANSFORM_SEGMENT_DEVIATION_RADIANS, velocity_delta_time=1.0, anchor_plate_id=0): """ Calculates spreading rate and length of ridge segments of spreading features (mid-ocean ridges) of resolved topologies at specified time. The transform segments of spreading features are ignored. Resolves topologies at 'time', tessellates all resolved spreading features to within 'threshold_sampling_distance_radians' radians and returns a list of tuples where each tuple represents a tessellated point and contains the following parameters: - point longitude - point latitude - spreading velocity magnitude (in cm/yr) - length of arc segment (in degrees) that current point is on rotation_features_or_model: Rotation model or feature collection(s), or list of features, or filename(s). topology_features: Topology feature collection(s), or list of features, or filename(s) or any combination of those. time: Reconstruction time to resolved topologies. threshold_sampling_distance_radians: Threshold sampling distance along spreading features (in radians). spreading_feature_types: Only spreading features with a feature type contained in this list are considered. If None then all spreading features are considered. transform_segment_deviation_in_radians: How much a segment can deviate from the stage pole before it's considered a transform segment (in radians). velocity_delta_time: Delta time interval used to calculate spreading velocity. Returns: List of the tuples described above. """ time = float(time) # Turn rotation data into a RotationModel (if not already). rotation_model = pygplates.RotationModel(rotation_features_or_model) # Turn topology data into a list of features (if not already). topology_features = pygplates.FeaturesFunctionArgument(topology_features) # Resolve our topological plate polygons (and deforming networks) to the current 'time'. # We generate both the resolved topology boundaries and the boundary sections between them. resolved_topologies = [] shared_boundary_sections = [] pygplates.resolve_topologies(topology_features.get_features(), rotation_model, resolved_topologies, time, shared_boundary_sections, anchor_plate_id) # List of tesselated spreading points and associated spreading parameters for the current 'time'. output_data = [] # Iterate over the shared boundary sections of all resolved topologies. for shared_boundary_section in shared_boundary_sections: spreading_feature = shared_boundary_section.get_feature() # Skip sections that are not spreading features (if requested). if (spreading_feature_types and spreading_feature.get_feature_type() not in spreading_feature_types): continue # Find the stage rotation of the spreading feature in the frame of reference of its reconstructed geometry at the current 'time'. # The stage pole can then be directly geometrically compared to the reconstructed spreading geometry. spreading_stage_rotation = separate_ridge_transform_segments.get_stage_rotation_for_reconstructed_geometry( spreading_feature, rotation_model, time) if not spreading_stage_rotation: # Skip current feature - it's not a spreading feature. continue # Iterate over the shared sub-segments of the current line. # These are the parts of the line that actually contribute to topological boundaries. for shared_sub_segment in shared_boundary_section.get_shared_sub_segments( ): # Split into ridge and transform segments. ridge_and_transform_segment_geometries = separate_ridge_transform_segments.separate_geometry_into_ridges_and_transforms( spreading_stage_rotation, shared_sub_segment.get_resolved_geometry(), transform_segment_deviation_in_radians) if not ridge_and_transform_segment_geometries: # Skip shared sub segment - it's not a polyline (or polygon). continue # Only interested in ridge segments. ridge_sub_segment_geometries, _ = ridge_and_transform_segment_geometries # Ensure the ridge sub-segments are tessellated to within the threshold sampling distance. tessellated_shared_sub_segment_polylines = [ ridge_sub_segment_geometry.to_tessellated( threshold_sampling_distance_radians) for ridge_sub_segment_geometry in ridge_sub_segment_geometries ] # Iterate over the great circle arcs of the tessellated polylines to get the arc midpoints and lengths. # There is an arc between each adjacent pair of points in the polyline. arc_midpoints = [] arc_lengths = [] for tessellated_shared_sub_segment_polyline in tessellated_shared_sub_segment_polylines: for arc in tessellated_shared_sub_segment_polyline.get_segments( ): if not arc.is_zero_length(): arc_midpoints.append(arc.get_arc_point(0.5)) arc_lengths.append(arc.get_arc_length()) # Shouldn't happen, but just in case ridge sub-segment polylines coincide with points. if not arc_midpoints: continue # Calculate the spreading velocities at the arc midpoints. # # Note that the stage rotation can be used directly on the reconstructed geometries because # it is already in the frame of reference of the reconstructed geometries. spreading_velocity_vectors = pygplates.calculate_velocities( arc_midpoints, spreading_stage_rotation, velocity_delta_time, pygplates.VelocityUnits.cms_per_yr) for arc_index in range(len(arc_midpoints)): arc_midpoint = arc_midpoints[arc_index] arc_length = arc_lengths[arc_index] lat, lon = arc_midpoint.to_lat_lon() spreading_velocity_magnitude = spreading_velocity_vectors[ arc_index].get_magnitude() # The data will be output in GMT format (ie, lon first, then lat, etc). output_data.append((lon, lat, spreading_velocity_magnitude, math.degrees(arc_length))) return output_data
# # Some testing/example code. # import time print('Loading coastline polygons and rotation model...') coastline_features = pygplates.FeatureCollection( '../../../../sample_data/2.0/SampleData/FeatureCollections/Coastlines/Matthews_etal_GPC_2016_Coastlines.gpmlz' ) rotation_model = pygplates.RotationModel( '../../../../sample_data/2.0/SampleData/FeatureCollections/Rotations/Matthews_etal_GPC_2016_410-0Ma_GK07.rot' ) print('Reconstructing coastline polygons...') reconstruction_time = 0 coastline_reconstructed_feature_geometries = [] pygplates.reconstruct(coastline_features, rotation_model, coastline_reconstructed_feature_geometries, reconstruction_time) polygons = [] polygon_features = []
while rfg2_index < len(reconstructed_feature_geometries): rfg2 = reconstructed_feature_geometries[rfg2_index] rfg2_geom = rfg2.get_reconstructed_geometry() # Compare the geometries of rfg1 and rfg2. # Test for duplicate geometries. if rfg1_geom == rfg2_geom: del reconstructed_feature_geometries[rfg2_index] rfg2_index -= 1 rfg2_index += 1 rfg1_index += 1 rotation_model = pygplates.RotationModel(rotation_file) proximity_features = list(pygplates.FeatureCollection(proximity_features_file)) print('{:<10} {:<10}'.format('Age(Ma)', 'Length(Kms)')) # Time range 0-230Ma in 1My intervals. for time in range(0, 231): length_in_kms = 0 # Reconstruct the proximity features that exist at the current 'time'. proximity_reconstructed_feature_geometries = [] pygplates.reconstruct(proximity_features, rotation_model, proximity_reconstructed_feature_geometries, time) # Remove any 'exact' duplicate reconstructed geometries.
def coregLoop(pointlist, ages, plateIDs): ''' coregLoop This script reconstructs a shapefile of points to their birth time and coregisters each point with another set of points, or a raster file. INPUTS: pointlist - list of lat/lon ages - list of ages corresponding to lat/lon point plateIDs - list of plateIDs corresponding to lat/lon point. Hardcoded filenames/variables must be changed below: input_rotation_filename - Rotation file rasterfile - Time dependent raster files f - Time dependent kinemtic csv outputs from 'convergence.py' OUTPUTS: Coregistered array: List of lat/lons with properties. METHOD: Takes a set of points Rotates the points back to their birth position Determines the point's birth position geophysical properties (coregisters) ''' #Set up a list to store the data timeSteps = 1 # +- Myrs around point to store. Default 1 which means just the measured point age. noVariables = 18 #The number of variables you save Nshp = len(pointlist) coregData = numpy.zeros((Nshp, timeSteps, noVariables)) #Create a rotation model to rotate the points back in time input_rotation_filename = "Muller_gplates/Global_EarthByte_230-0Ma_GK07_AREPS.rot" file_registry = pygplates.FeatureCollectionFileFormatRegistry() rotation_feature_collection = file_registry.read(input_rotation_filename) rotation_model = pygplates.RotationModel([rotation_feature_collection]) #Loop over all the samples, coregistering each one. for i, currentPoint in enumerate(pointlist): lat = currentPoint[1] lon = currentPoint[0] age = ages[i] plateID = int(plateIDs[i]) print("Deposit:", i, "of", Nshp, "Lat:", lat, "Lon:", lon, "Age:", age, "PlateID:", plateID) #Loop through each time step in the plate model for time in xrange(0, 230, 1): #If the point was formed at the current time (or [timeStepsMyr ] prior/after) then we #want to find the surrounding plate properties. #if (time > (age-10)) and (time < (age+10)) or (time > (age+20)) and (time < (age+30)): if (time > (age - timeSteps)) and (time < (age + timeSteps)): t = int(numpy.floor(time - age)) #print(t,time,age) #A raster file, to coregister with, these points have already been rotated rasterfile = "Muller_etal_2016_AREPS_Agegrids_v1.11/netCDF_0-230Ma/EarthByte_AREPS_v1.11_Muller_etal_2016_AgeGrid-" + str( time) + ".nc" [x, y, z] = gridRead(rasterfile) #A vector file to coregister with, these points have already been rotated f = numpy.loadtxt("Muller_convergence/subStats_" + str(time) + ".csv", delimiter=',') lonlat = f[:, 0:2] #-------------------# #Reconstruct a point to its birth position #-------------------# latlonPoint = pygplates.LatLonPoint(lat, lon) point_to_rotate = pygplates.convert_lat_lon_point_to_point_on_sphere( latlonPoint) finite_rotation = rotation_model.get_rotation(time, plateID) birthPosition = finite_rotation * point_to_rotate latlonBirth = pygplates.convert_point_on_sphere_to_lat_lon_point( birthPosition) #allPoints = finite_rotation * pointSet_to_rotate latBirth = latlonBirth.get_latitude() lonBirth = latlonBirth.get_longitude() #-------------------# #Set the points for coregistering region = 5.0 #degrees #-------------------# #Coregisterring raster 1 #-------------------# #Find the region in index units r = numpy.round(region / (x[1] - x[0])) #Find the index unit of lat and lon idxLon = (numpy.abs(x - lonBirth)).argmin() idxLat = (numpy.abs(y - latBirth)).argmin() #Raster 1 c2 = coregRaster([idxLon, idxLat], z, r) #Hack to search further around the age grid if it can't find a match, note index units (not degrees) if numpy.isnan(c2): c2 = coregRaster([idxLon, idxLat], z, r + 150.0) print("Trying raster region: ", r + 150.0) #-------------------# #Coregisterring vector 1 #-------------------# index = coregPoint([lonBirth, latBirth], lonlat, region) if index == 'inf': print("trying index region", region + 15) index = coregPoint([lonBirth, latBirth], lonlat, region + 15.0) if numpy.isnan(c2) or index == 'inf': print("Skipping:", i, age, t, time, c2, index, lonBirth, latBirth) else: #Vector 1 segmentLength = f[index, 3] slabLength = f[index, 9] distSlabEdge = f[index, 15] SPcoregNor = f[index, 4] SPcoregPar = f[index, 12] OPcoregNor = f[index, 5] OPcoregPar = f[index, 13] CONVcoregNor = f[index, 10] CONVcoregPar = f[index, 11] subPolCoreg = f[index, 8] subOblCoreg = f[index, 7] coregData[i, t, :] = [ lon, lat, lonBirth, latBirth, age, t, c2, segmentLength, slabLength, distSlabEdge, SPcoregNor, SPcoregPar, OPcoregNor, OPcoregPar, CONVcoregNor, CONVcoregPar, subPolCoreg, subOblCoreg ] #Return the filled coregistered array return (coregData)
def coregLoopHistory(pointlist, ts0=0, ts1=230, plateID=201): ''' coregLoopHistory This script reconstructs a list of points throughout history and coregisters each point with another set of points, or a raster file. INPUTS: pointlist - list of lat/lon ts0 - time step to rotate points from (probably 0Ma) ts1 - time step to rotate points to (probably 230Ma). Hardcoded filenames/variables must be changed below: input_rotation_filename - Rotation file rasterfile - Time dependent raster files f - Time dependent kinemtic csv outputs from 'convergence.py' OUTPUTS: Coregistered array: List of lat/lons with properties. METHOD: Takes a set of points Rotates the points back to their birth position Determines the point's birth position geophysical properties (coregisters) ''' #Set up an array to store the data timeSteps = ts1 - ts0 #The length of time before mineralisation you care about noVariables = 18 #The number of variables you save Nshp = len(pointlist) coregData = numpy.zeros((Nshp, timeSteps, noVariables)) #Create a rotation model to rotate the points back in time input_rotation_filename = "Muller_gplates/Global_EarthByte_230-0Ma_GK07_AREPS.rot" file_registry = pygplates.FeatureCollectionFileFormatRegistry() rotation_feature_collection = file_registry.read(input_rotation_filename) rotation_model = pygplates.RotationModel([rotation_feature_collection]) #Loop through each time step in the plate model for time in xrange(ts0, ts1, 1): #A raster file, to coregister with, these points have already been rotated rasterfile = "Muller_etal_2016_AREPS_Agegrids_v1.11/netCDF_0-230Ma/EarthByte_AREPS_v1.11_Muller_etal_2016_AgeGrid-" + str( time) + ".nc" [x, y, z] = gridRead(rasterfile) #A vector file to coregister with, these points have already been rotated f = numpy.loadtxt("Muller_convergence/subStats_" + str(time) + ".csv", delimiter=',') lonlat = f[:, 0:2] for i, currentPoint in enumerate(pointlist): shapeArray = currentPoint age = ts0 t = time - age print(i, age, time, t, plateID) #-------------------# #Reconstruct a point to its birth position #-------------------# latlonPoint = pygplates.LatLonPoint(shapeArray[1], shapeArray[0]) point_to_rotate = pygplates.convert_lat_lon_point_to_point_on_sphere( latlonPoint) finite_rotation = rotation_model.get_rotation(time, plateID) birthPosition = finite_rotation * point_to_rotate latlonBirth = pygplates.convert_point_on_sphere_to_lat_lon_point( birthPosition) #allPoints = finite_rotation * pointSet_to_rotate latBirth = latlonBirth.get_latitude() lonBirth = latlonBirth.get_longitude() #-------------------# #Set the points for coregistering region = 5.0 #degrees #-------------------# #Coregisterring raster 1 #-------------------# #Find the region in index units r = numpy.round(region / (x[1] - x[0])) #Find the index unit of lat and lon idxLon = (numpy.abs(x - lonBirth)).argmin() idxLat = (numpy.abs(y - latBirth)).argmin() #Raster 1 c2 = coregRaster([idxLon, idxLat], z, r) #Hack to search further around the age grid if it can't find a match, \ #note index units (not degrees) if numpy.isnan(c2): c2 = coregRaster([idxLon, idxLat], z, r + 150.0) print("Trying raster region: ", r + 150.0) #-------------------# #Coregisterring vector 1 #-------------------# index = coregPoint([lonBirth, latBirth], lonlat, region) if index == 'inf': print("trying index region", region + 15) index = coregPoint([lonBirth, latBirth], lonlat, region + 15.0) if numpy.isnan(c2) or index == 'inf': #if we have some null data, let's save it anyway, see what happens print("Skipping:", i, age, t, time, c2, index, lonBirth, latBirth) else: #Vector 1 segmentLength = f[index, 3] slabLength = f[index, 9] distSlabEdge = f[index, 15] SPcoregNor = f[index, 4] SPcoregPar = f[index, 12] OPcoregNor = f[index, 5] OPcoregPar = f[index, 13] CONVcoregNor = f[index, 10] CONVcoregPar = f[index, 11] subPolCoreg = f[index, 8] subOblCoreg = f[index, 7] coregData[i, t, :] = [ shapeArray[0], shapeArray[1], lonBirth, latBirth, age, t, c2, segmentLength, slabLength, distSlabEdge, SPcoregNor, SPcoregPar, OPcoregNor, OPcoregPar, CONVcoregNor, CONVcoregPar, subPolCoreg, subOblCoreg ] return (coregData)
'--output_filename_extension', type=str, default='{0}'.format(DEFAULT_OUTPUT_FILENAME_EXTENSION), help= "The filename extension of the output files containing the resolved topological boundaries and sections " "- the default extension is '{0}' - supported extensions include 'shp', 'gmt' and 'xy'." .format(DEFAULT_OUTPUT_FILENAME_EXTENSION)) parser.add_argument( 'output_filename_prefix', type=str, nargs='?', default='{0}'.format(DEFAULT_OUTPUT_FILENAME_PREFIX), help= "The prefix of the output files containing the resolved topological boundaries and sections " "- the default prefix is '{0}'".format(DEFAULT_OUTPUT_FILENAME_PREFIX)) # Parse command-line options. args = parser.parse_args() rotation_model = pygplates.RotationModel(args.rotation_filenames) topological_features = [ pygplates.FeatureCollection(topology_filename) for topology_filename in args.topology_filenames ] for reconstruction_time in args.reconstruction_times: reconstruct_features(rotation_model, topological_features, reconstruction_time, args.output_filename_prefix, args.output_filename_extension)
def calc_subducting_sediment_volume(time): rotation_model = pygplates.RotationModel(rotation_filename) topology_features = pygplates.FeaturesFunctionArgument( (topology_dir + '/Global_EarthByte_230-0Ma_GK07_AREPS_PlateBoundaries.gpml', topology_dir + '/Global_EarthByte_230-0Ma_GK07_AREPS_Topology_BuildingBlocks.gpml')).get_features() sediment_thickness_grid_filename = sediment_thickness_grid_dir + '/sed_thick_0.2d_{0}.grd'.format(time) subduction_convergence_data = subduction_convergence.subduction_convergence( rotation_model, topology_features, tessellation_threshold_radians, time) subduction_points = [pygplates.PointOnSphere(data[1], data[0]) for data in subduction_convergence_data] # Sample the sediment thickness raster at the subduction points. sediment_thicknesses = raster_query.query_raster_at_points( sediment_thickness_grid_filename, subduction_points, search_radius_radians, smoothing_radius_radians) subducting_lon_lat_thickness_velocity_volume_list = [] # Iterate over subduction points/thicknesses and calculate statistics (including subducting volume). weighted_mean_subducting_sed_thickness = 0.0 weighted_second_moment_subducting_sed_thickness = 0.0 total_subducting_length_metres = 0.0 total_subducting_sediment_volume_metres_3_per_year = 0.0 for subduction_point_index, sediment_thickness in enumerate(sediment_thicknesses): if math.isnan(sediment_thickness): continue subduction_convergence_item = subduction_convergence_data[subduction_point_index] subducting_lon = subduction_convergence_item[0] subducting_lat = subduction_convergence_item[1] convergence_velocity_magnitude_cm_per_yr = subduction_convergence_item[2] convergence_obliquity_degrees = subduction_convergence_item[3] #absolute_velocity_magnitude = subduction_convergence_item[4] #absolute_obliquity_degrees = subduction_convergence_item[5] subducting_length_degrees = subduction_convergence_item[6] #subducting_arc_normal_azimuth = subduction_convergence_item[7] #subducting_plate_id = subduction_convergence_item[8] #overriding_plate_id = subduction_convergence_item[9] subducting_length_metres = ( math.radians(subducting_length_degrees) * 1e3 * pygplates.Earth.mean_radius_in_kms) weighted_mean_subducting_sed_thickness += subducting_length_metres * sediment_thickness weighted_second_moment_subducting_sed_thickness += subducting_length_metres * sediment_thickness * sediment_thickness total_subducting_length_metres += subducting_length_metres convergence_normal_velocity_metres_per_year = ( # 1e-2 converts cm/y to m/y... 1e-2 * math.fabs(convergence_velocity_magnitude_cm_per_yr) * # Negative convergence handled by cos(obliquity_angle)... math.cos(math.radians(convergence_obliquity_degrees))) subducting_sediment_volume_metres_3_per_year = ( sediment_thickness * subducting_length_metres * convergence_normal_velocity_metres_per_year) total_subducting_sediment_volume_metres_3_per_year += subducting_sediment_volume_metres_3_per_year subducting_lon_lat_thickness_velocity_volume_list.append(( subducting_lon, subducting_lat, sediment_thickness, subducting_sediment_volume_metres_3_per_year / subducting_length_metres, # cms/year ... 1e2 * convergence_normal_velocity_metres_per_year)) # mean = M = sum(Ci * Xi) / sum(Ci) # std_dev = sqrt[sum(Ci * (Xi - M)^2) / sum(Ci)] # = sqrt[(sum(Ci * Xi^2) - 2 * M * sum(Ci * Xi) + M^2 * sum(Ci)) / sum(Ci)] # = sqrt[(sum(Ci * Xi^2) - 2 * M * M * sum(Ci) + M^2 * sum(Ci)) / sum(Ci)] # = sqrt[(sum(Ci * Xi^2) - M^2 * sum(Ci)) / sum(Ci)] # = sqrt[(sum(Ci * Xi^2) / sum(Ci) - M^2] mean_sed_thickness = weighted_mean_subducting_sed_thickness / total_subducting_length_metres variance_sed_thickness = ( (weighted_second_moment_subducting_sed_thickness / total_subducting_length_metres) - mean_sed_thickness * mean_sed_thickness) std_dev_sed_thickness = math.sqrt(variance_sed_thickness) if variance_sed_thickness > 0.0 else 0.0 return (time, subducting_lon_lat_thickness_velocity_volume_list, mean_sed_thickness, std_dev_sed_thickness, total_subducting_length_metres, total_subducting_sediment_volume_metres_3_per_year)
def kinloop(timeFrom,timeTo,data,input_rotation_filename): ''' Determines the absolute and relative velocities of the plates and trench. INPUT (with examples): timeFrom=2 #integer timeTo=1 #integer data = [[14.7703, 43.5369, 701, 301, 301], [18.8934, 41.5683, 701, 301, 301], [18.6062, 39.7998, 701, 301, 301], [19.4349, 39.3242, 701, 301, 301]] #List of points [[Lon, Lat, SPid, TRENCHid, OPid]] input_rotation_filename='Shephard_etal_ESR2013_Global_EarthByte_2013.rot' #String OUTPUT: (array equivalent to 'data' plus Absoulte XYZ and Convergence XYZ velocity components.) [14.7703, 43.5369, 701, 301, 301, -13.02077,10.4195,10.45488,-4.86172, -4.62026,6.18716] WARNING: If this function is used stand-alone, without an idea of left or right, then it may be backward. Points should be entered CW. ''' #Set the times of interest #timeFrom=3 #from xx Ma #timeTo=2 # to xx Ma #Read the SubdctionZoneAttributes data kinematicsArray=data #Read the rotation file and build a rotation model #input_rotation_filename = "/Users/nbutter/DataMining/CODE/SubductionZoneAttributes/oldTestdata/Global_EarthByte_TPW_CK95G94_PP_20110412.rot" file_registry = pygplates.FeatureCollectionFileFormatRegistry() rotation_feature_collection = file_registry.read(input_rotation_filename) rotation_model = pygplates.RotationModel([rotation_feature_collection]) #Build the rotations for the times we want fromTimeRotation=rotation_model.get_reconstruction_tree(timeFrom) toTimeRotation=rotation_model.get_reconstruction_tree(timeTo) #Make an array to store our data in speedArray=[] reversedSub=0 #Initilise this here in case the data does not have headers #Loop through all the SubdctionZoneAttributes data and find velocities for index, point in enumerate(kinematicsArray[:]): #print point[0] #See if the point is not a header, or if the next point is not a header if isinstance(point[0],str): #Also, if it is a header, get the order of the points if point[0].find('Reversed') != -1: reversedSub=int(point[-1]) #print reverse if len(point) == 5: lon = float(point[0]) lat = float(point[1]) OPid = int(point[4]) TRENCHid = int(point[3]) SPid = int(point[2]) #Convert point LatLon to XYZ pointXYZ, pointXYZcart = latlon2pygplates(lat,lon) #Get the Euler poles for each of the relevant rotations stageTrench = pygplates.ReconstructionTree.get_equivalent_stage_rotation(fromTimeRotation,toTimeRotation,TRENCHid) poletTrench,angleTrench = stageTrench.get_euler_pole_and_angle() poleTrench = [poletTrench.get_x(), poletTrench.get_y(), poletTrench.get_z()] #Absolut velocity is the motion of the SP stageSP = pygplates.ReconstructionTree.get_equivalent_stage_rotation(fromTimeRotation,toTimeRotation,SPid) poletSP,angleSP = stageSP.get_euler_pole_and_angle() #If you want the latitude and longitude, rather than the cartesian: #poleSPLatLon = pygplates.convert_point_on_sphere_to_lat_lon_point(poleSP) #SPLatLon = [poleSPLatLon.get_latitude(), poleSPLatLon.get_longitude()] poleSP = [poletSP.get_x(), poletSP.get_y(), poletSP.get_z()] #Convergence is the relative rotation between the trench and SP #if reversedSub==1: #convRotation = pygplates.get_relative_stage_rotation(fromTimeRotation,toTimeRotation,TRENCHid,SPid) #else: convRotation = pygplates.ReconstructionTree.get_relative_stage_rotation(fromTimeRotation,toTimeRotation,SPid,TRENCHid) poletCONV,angleCONV = convRotation.get_euler_pole_and_angle() poleCONV = [poletCONV.get_x(), poletCONV.get_y(), poletCONV.get_z()] #The OP motion stageOP = pygplates.ReconstructionTree.get_equivalent_stage_rotation(fromTimeRotation,toTimeRotation,OPid) poletOP,angleOP = stageOP.get_euler_pole_and_angle() poleOP = [poletOP.get_x(), poletOP.get_y(), poletOP.get_z()] #Angular velocity (Degrees / Myr) #but need it in radians.. not used omegaCONV = numpy.degrees(angleCONV)/(timeFrom-timeTo) omegaSP = numpy.degrees(angleSP)/(timeFrom-timeTo) #Velocity vectors at each point in (Earth Radius Units) / Myr absoluteV = numpy.cross(poleSP,pointXYZcart) * angleSP/(timeFrom-timeTo) convergenceV = numpy.cross(poleCONV,pointXYZcart) * angleCONV/(timeFrom-timeTo) opV = numpy.cross(poleOP,pointXYZcart) * angleOP/(timeFrom-timeTo) trenchV = numpy.cross(poleTrench,pointXYZcart) * angleTrench/(timeFrom-timeTo) #Velocivites vectors in mm/yr (km/Myr) Rearth=6371.0 # m vABS = absoluteV * Rearth vCONV = convergenceV * Rearth vOP = opV * Rearth vTrench = trenchV * Rearth speedArray.append([lon,lat,SPid,TRENCHid,OPid,\ round(vABS[0],5),round(vABS[1],5),round(vABS[2],5),\ round(vCONV[0],5),round(vCONV[1],5),round(vCONV[2],5),\ round(vOP[0],5),round(vOP[1],5),round(vOP[2],5),\ round(vTrench[0],5),round(vTrench[1],5),round(vTrench[2],5),\ int(SPid), int(TRENCHid), int(OPid)]) #print [lon,lat,SPid,TRENCHid,OPid,round(vABS[0],5),round(vABS[1],5),round(vABS[2],5),round(vCONV[0],5),round(vCONV[1],5),round(vCONV[2],5)] #If it is a header, just print it back out. else: #pass speedArray.append(point) return(speedArray)
def reconstruct_seeds(input_rotation_filenames, topology_features, seedpoints_output_dir, mor_seedpoint_filename, initial_ocean_seedpoint_filename, max_time, min_time, time_step, grd_output_dir, subduction_collision_parameters=(5.0, 10.0), continent_mask_file_pattern=None): # reconstruct the seed points using the reconstruct_by_topologies function # returns the result either as lists or dumps to an ascii file rotation_model = pygplates.RotationModel(input_rotation_filenames) print('Begin assembling seed points and reconstructing by topologies....') # load features to reconstruct cp = [] # current_point # TODO more verbose names for cp and at at = [] # appearance_time birth_lat = [] # latitude_of_crust_formation prev_lat = [] prev_lon = [] seeds_at_start_time = pygplates.FeatureCollection( initial_ocean_seedpoint_filename) for feature in seeds_at_start_time: cp.append(feature.get_geometry()) at.append(feature.get_valid_time()[0]) birth_lat.append(feature.get_geometry().to_lat_lon_list()[0] [0]) # Why use a list here?? prev_lat.append(feature.get_geometry().to_lat_lon_list()[0][0]) prev_lon.append(feature.get_geometry().to_lat_lon_list()[0][1]) #seeds_from_topologies = pygplates.FeatureCollection(mor_seedpoint_filename) seeds_from_topologies = [] for time in np.arange(max_time, min_time - time_step, -time_step): filename = './{:s}/MOR_plus_one_points_{:0.2f}.gmt'.format( seedpoints_output_dir, time) print('merging seeds from file {:s}'.format(filename)) features = pygplates.FeatureCollection(filename) for feature in features: seeds_from_topologies.append(feature) for feature in seeds_from_topologies: if feature.get_valid_time()[0] < max_time: cp.append(feature.get_geometry()) at.append(feature.get_valid_time()[0]) birth_lat.append(feature.get_geometry().to_lat_lon_list()[0][0]) prev_lat.append(feature.get_geometry().to_lat_lon_list()[0][0]) prev_lon.append(feature.get_geometry().to_lat_lon_list()[0][1]) point_id = range(len(cp)) # specify the collision detection default_collision = rbt.DefaultCollision( feature_specific_collision_parameters=[( pygplates.FeatureType.gpml_subduction_zone, subduction_collision_parameters)]) # specify the collision depending on whether the continent collision is specified if continent_mask_file_pattern: collision_spec = rbt.ContinentCollision(continent_mask_file_pattern, default_collision) else: collision_spec = default_collision print('preparing reconstruction by topologies....') topology_reconstruction = rbt.ReconstructByTopologies( rotation_model, topology_features, max_time, min_time, time_step, cp, point_begin_times=at, detect_collisions=collision_spec) # Initialise the reconstruction. topology_reconstruction.begin_reconstruction() # Loop over the reconstruction times until reached end of the reconstruction time span, or # all points have entered their valid time range *and* either exited their time range or # have been deactivated (subducted forward in time or consumed by MOR backward in time). while True: print('reconstruct by topologies: working on time {:0.2f} Ma'.format( topology_reconstruction.get_current_time())) curr_points = topology_reconstruction.get_active_current_points() print(len(cp), len(prev_lat)) curr_lat_lon_points = [point.to_lat_lon() for point in curr_points] if curr_lat_lon_points: curr_latitudes, curr_longitudes = zip(*curr_lat_lon_points) seafloor_age = [] birth_lat_snapshot = [] point_id_snapshot = [] prev_lat_snapshot = [] prev_lon_snapshot = [] for point_index, current_point in enumerate( topology_reconstruction.get_all_current_points()): if current_point is not None: #all_birth_ages.append(at[point_index]) seafloor_age.append( at[point_index] - topology_reconstruction.get_current_time()) birth_lat_snapshot.append(birth_lat[point_index]) point_id_snapshot.append(point_id[point_index]) prev_lat_snapshot.append(prev_lat[point_index]) prev_lon_snapshot.append(prev_lon[point_index]) prev_lat[point_index] = current_point.to_lat_lon()[0] prev_lon[point_index] = current_point.to_lat_lon()[1] write_xyz_file( '{:s}/gridding_input/gridding_input_{:0.1f}Ma.xy'.format( grd_output_dir, topology_reconstruction.get_current_time()), zip(curr_longitudes, curr_latitudes, seafloor_age, birth_lat_snapshot, point_id_snapshot)) if not topology_reconstruction.reconstruct_to_next_time(): break print('done') return
def get_initial_ocean_seeds(topology_features, input_rotation_filenames, COBterrane_file, output_directory, time, initial_ocean_mean_spreading_rate, initial_ocean_healpix_sampling, area_threshold, mask_sampling=0.5): # Get a set of points at the oldest time for a reconstruction sequence, such that the points # populate the ocean basins (defined using the COB Terrane polygons) and are assigned ages assuming # a uniform average spreading rate combined with the distance of each point to the nearest # MidOceanRidge feature in the resolved plate boundary of the the plate containing the point print( 'Begin creating seed points for initial ocean at reconstruction start time....' ) rotation_model = pygplates.RotationModel(input_rotation_filenames) cobter = get_merged_cob_terrane_polygons(COBterrane_file, rotation_model, time, mask_sampling, area_threshold) ocean_points = pg.rasterise_paleogeography( cobter, rotation_model, time, sampling=initial_ocean_healpix_sampling, meshtype='healpix', masking='Inside') #ocean_points = rasterise_polygons(cobter, rotation_model,time, # sampling=initial_ocean_healpix_sampling, meshtype='healpix', # masking='Inside') resolved_topologies = [] shared_boundary_sections = [] pygplates.resolve_topologies(topology_features, rotation_model, resolved_topologies, time, shared_boundary_sections) pX, pY, pZ = pg.find_distance_to_nearest_ridge(resolved_topologies, shared_boundary_sections, ocean_points) # divide spreading rate by 2 to use half spreading rate pAge = np.array(pZ) / (initial_ocean_mean_spreading_rate / 2.) initial_ocean_point_features = [] for point in zip(pX, pY, pAge): point_feature = pygplates.Feature() point_feature.set_geometry(pygplates.PointOnSphere(point[1], point[0])) # note that we add 'time' to the age at the time of computation # to get the valid time in Ma point_feature.set_valid_time(point[2] + time, -1) initial_ocean_point_features.append(point_feature) pygplates.FeatureCollection(initial_ocean_point_features).write( '{:s}/age_from_distance_to_mor_{:0.2f}Ma.gmt'.format( output_directory, time)) print('done')
def reconstruct_feature_collection(request): if request.method == 'POST': params = request.POST elif request.method == 'GET': params = request.GET else: return HttpResponseBadRequest('Unrecognized request type') anchor_plate_id = params.get('pid', 0) if 'time' in params: time = params['time'] elif 'geologicage' in params: time = params['geologicage'] else: time = 140 #default reconstruction age output_format = params.get('output', 'geojson') fc_str = params.get('feature_collection') model = str(params.get('model',settings.MODEL_DEFAULT)) if 'keep_properties' in params: keep_properties = True else: keep_properties = False try: timef = float(time) except: return HttpResponseBadRequest('The "time" parameter is invalid ({0}).'.format(time)) try: anchor_plate_id = int(anchor_plate_id) except: return HttpResponseBadRequest('The "pid" parameter is invalid ({0}).'.format(anchor_plate_id)) # Convert geojson input to gplates feature collection features=[] try: fc = json.loads(fc_str)#load the input feature collection for f in fc['features']: geom = f['geometry'] feature = pygplates.Feature() if geom['type'] == 'Point': feature.set_geometry(pygplates.PointOnSphere( float(geom['coordinates'][1]), float(geom['coordinates'][0]))) if geom['type'] == 'LineString': feature.set_geometry( pygplates.PolylineOnSphere([(point[1],point[0]) for point in geom['coordinates']])) if geom['type'] == 'Polygon': feature.set_geometry( pygplates.PolygonOnSphere([(point[1],point[0]) for point in geom['coordinates'][0]])) if geom['type'] == 'MultiPoint': feature.set_geometry( pygplates.MultiPointOnSphere([(point[1],point[0]) for point in geom['coordinates']])) if keep_properties and 'properties' in f: for pk in f['properties']: p = f['properties'][pk] if isinstance(p, str): p=str(p) feature.set_shapefile_attribute(str(pk),p) features.append(feature) except Exception as e: #print e return HttpResponseBadRequest('Invalid input feature collection') model_dict = get_reconstruction_model_dict(model) if not model_dict: return HttpResponseBadRequest('The "model" ({0}) cannot be recognized.'.format(model)) rotation_model = pygplates.RotationModel([str('%s/%s/%s' % (settings.MODEL_STORE_DIR,model,rot_file)) for rot_file in model_dict['RotationFile']]) assigned_features = pygplates.partition_into_plates( settings.MODEL_STORE_DIR+model+'/'+model_dict['StaticPolygons'], rotation_model, features, properties_to_copy = [ pygplates.PartitionProperty.reconstruction_plate_id, pygplates.PartitionProperty.valid_time_period], partition_method = pygplates.PartitionMethod.most_overlapping_plate ) reconstructed_geometries = [] pygplates.reconstruct(assigned_features, rotation_model, reconstructed_geometries, timef, anchor_plate_id=anchor_plate_id) # convert feature collection back to geojson data = {"type": "FeatureCollection"} data["features"] = [] for g in reconstructed_geometries: geom = g.get_reconstructed_geometry() feature = {"type": "Feature"} feature["geometry"] = {} if isinstance(geom, pygplates.PointOnSphere): feature["geometry"]["type"] = "Point" p = geom.to_lat_lon_list()[0] feature["geometry"]["coordinates"] = [p[1], p[0]] elif isinstance(geom, pygplates.MultiPointOnSphere): feature["geometry"]["type"] = 'MultiPoint' feature["geometry"]["coordinates"] = [[lon,lat] for lat, lon in geom.to_lat_lon_list()] elif isinstance(geom, pygplates.PolylineOnSphere): feature["geometry"]["type"] = 'LineString' feature["geometry"]["coordinates"] = [[lon,lat] for lat, lon in geom.to_lat_lon_list()] elif isinstance(geom, pygplates.PolygonOnSphere): feature["geometry"]["type"] = 'Polygon' feature["geometry"]["coordinates"] = [[[lon,lat] for lat, lon in geom.to_lat_lon_list()]] else: return HttpResponseServerError('Unsupported Geometry Type.') feature["properties"] = {} if keep_properties: for pk in g.get_feature().get_shapefile_attributes(): feature["properties"][pk] = g.get_feature().get_shapefile_attribute(pk) #print feature["properties"] data["features"].append(feature) ret = json.dumps(pretty_floats(data)) #add header for CORS #http://www.html5rocks.com/en/tutorials/cors/ response = HttpResponse(ret, content_type='application/json') #TODO: response['Access-Control-Allow-Origin'] = '*' return response
def reconstruct_files(request): if not request.method == "POST": return HttpResponseBadRequest('expecting post requests!') try: print((request.FILES)) if not len(list(request.FILES.items())): return HttpResponseBadRequest("No File Received") if not os.path.isdir(settings.MEDIA_ROOT + "/rftmp"): os.makedirs(settings.MEDIA_ROOT + "/rftmp" ) reconstructable_files = [] for fs in request.FILES.lists(): for f in fs[1]: print((f.name)) (name,ext) = os.path.splitext(f.name) if ext in ['.shp', '.gpml','.gpmlz']: reconstructable_files.append(f.name) with open(settings.MEDIA_ROOT + "/rftmp/" + f.name, 'wb+') as fp: for chunk in f.chunks(): fp.write(chunk) time = request.POST.get('time', None) model = request.POST.get('model',settings.MODEL_DEFAULT) print(model) model_dict = get_reconstruction_model_dict(model) if not model_dict: return HttpResponseBadRequest('The "model" ({0}) cannot be recognized.'.format(model)) rotation_model = pygplates.RotationModel([str('%s/%s/%s' % (settings.MODEL_STORE_DIR,model,rot_file)) for rot_file in model_dict['RotationFile']]) static_polygons_filename = str('%s/%s/%s' % (settings.MODEL_STORE_DIR,model,model_dict['StaticPolygons'])) for f in reconstructable_files: #print(f) features = pygplates.partition_into_plates( static_polygons_filename, rotation_model, (settings.MEDIA_ROOT + "/rftmp/" + f).encode("utf-8"), partition_method = pygplates.PartitionMethod.most_overlapping_plate, properties_to_copy = [pygplates.PartitionProperty.reconstruction_plate_id, pygplates.PartitionProperty.valid_time_period] ) feature_collection = pygplates.FeatureCollection(features) feature_collection.write((settings.MEDIA_ROOT + "/rftmp/" + f+'.partitioned.gpml').encode("utf-8")) if not os.path.isdir(settings.MEDIA_ROOT + "/rftmp/dst/"): os.makedirs(settings.MEDIA_ROOT + "/rftmp/dst/" ) pygplates.reconstruct((settings.MEDIA_ROOT + "/rftmp/" + f+'.partitioned.gpml').encode("utf-8"), rotation_model, ((settings.MEDIA_ROOT + "/rftmp/dst/" + f + '_' + model + '_' + str(time) + 'Ma').replace('.','_') + '.shp').encode("utf-8"), float(time)) s = io.StringIO() zf = zipfile.ZipFile(s, "w") #settings.MEDIA_ROOT + '/rftmp/dst/reconstructed_files.zip', 'w', zipfile.ZIP_DEFLATED) for r, d, files in os.walk(settings.MEDIA_ROOT + "/rftmp/dst/"): if not files: return HttpResponseServerError('No output files have been created!') for f in files: zf.write(os.path.join(r, f), 'reconstructed_files/'+f) zf.close() #f = StringIO(file(settings.MEDIA_ROOT + '/rftmp/dst/reconstructed_files.zip', "rb").read()) response = HttpResponse(s.getvalue(), content_type = 'application/x-zip-compressed') response['Content-Disposition'] = 'attachment; filename=reconstructed_files.zip' #clear_folder(settings.MEDIA_ROOT + "/rftmp" ) #clear_folder(settings.MEDIA_ROOT + "/rftmp/dst") return response except: clear_folder(settings.MEDIA_ROOT + "/rftmp" ) clear_folder(settings.MEDIA_ROOT + "/rftmp/dst") traceback.print_stack() traceback.print_exc(file=sys.stdout) err = traceback.format_exc() return HttpResponseBadRequest(err)