def run_grid_pip(time,points,polygons,rotation_model,grid_dims): reconstructed_polygons = [] pygplates.reconstruct(polygons,rotation_model,reconstructed_polygons,time) rpolygons = [] for polygon in reconstructed_polygons: if polygon.get_reconstructed_geometry(): rpolygons.append(polygon.get_reconstructed_geometry()) polygons_containing_points = points_in_polygons.find_polygons(points, rpolygons) lat = [] lon = [] zval = [] for pcp,point in zip(polygons_containing_points,points): lat.append(point.get_latitude()) lon.append(point.get_longitude()) if pcp is not None: zval.append(1) else: zval.append(0) bi = np.array(zval).reshape(grid_dims[0],grid_dims[1]) return bi
def run_grid_pip(recon_time, points, polygons, rotation_model, anchor_plate_id=0): reconstructed_polygons = [] pygplates.reconstruct(polygons, rotation_model, reconstructed_polygons, recon_time, anchor_plate_id=anchor_plate_id) rpolygons = [] for polygon in reconstructed_polygons: if polygon.get_reconstructed_geometry(): rpolygons.append(polygon.get_reconstructed_geometry()) polygons_containing_points = points_in_polygons.find_polygons( points, rpolygons) lat = [] lon = [] zval = [] for pcp, point in zip(polygons_containing_points, points): lat.append(point.get_latitude()) lon.append(point.get_longitude()) if pcp is not None: zval.append(1) else: zval.append(0) return zval
def run_grid_pnp(recon_time, points, spatial_tree_of_uniform_recon_points, polygons, rotation_model, anchor_plate_id=0, distance_threshold_radians=2): reconstructed_polygons = [] pygplates.reconstruct(polygons, rotation_model, reconstructed_polygons, recon_time, anchor_plate_id=anchor_plate_id) rpolygons = [] for polygon in reconstructed_polygons: if polygon.get_reconstructed_geometry(): rpolygons.append(polygon.get_reconstructed_geometry()) res = find_closest_geometries_to_points_using_points_spatial_tree( points, spatial_tree_of_uniform_recon_points, rpolygons, distance_threshold_radians=distance_threshold_radians, geometries_are_solid=True) pnp_test = [] for index in res: if index is not None: pnp_test.append(1) else: pnp_test.append(0) return pnp_test
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 reconstruct_coastlines(self): # #-----------Use pygplates to carry out the reconstruction # print 'Reconstructing coastlines...' pygplates.reconstruct(coastlines_filename, rotation_filenames, coastlines_output_basename + '.shp', self.reconstruction_time, self.anchor_plate)
def reconstruct_features(rotation_model, topological_features, reconstruction_time, output_filename_prefix, output_filename_extension): export_filename = 'reconstructed_{0!s}_{1}Ma.{2!s}'.format( output_filename_prefix, reconstruction_time, output_filename_extension) pygplates.reconstruct(topological_features, rotation_model, export_filename, reconstruction_time)
def reconstruct_mineral_deposits(self): pygplates.reconstruct(mineral_filename, rotation_filenames, mineral_output_basename + '.shp', self.reconstruction_time, self.anchor_plate) pygplates.reconstruct(mineral_AU_filename, rotation_filenames, mineral_AU_output_basename + '.shp', self.reconstruction_time, self.anchor_plate)
def reconstruct_continental_polygons(self): # #-----------Use pygplates to carry out the reconstruction # print('Reconstructing continental polygons...') pygplates.reconstruct(continental_polygons_filename, rotation_filenames, continental_polygons_output_basename + '.shp', self.reconstruction_time, self.anchor_plate)
def tree_snapshot(polygons, rotation_model, recon_time): reconstructed_polygons = [] pygplates.reconstruct(polygons,rotation_model,reconstructed_polygons,recon_time) uniq_plates_from_polygons = get_unique_plate_ids_from_reconstructed_features(reconstructed_polygons) reconstruction_tree = rotation_model.get_reconstruction_tree(recon_time) chains = get_plate_chains(uniq_plates_from_polygons, reconstruction_tree) return uniq_plates_from_polygons, chains, reconstruction_tree, reconstructed_polygons
def reconstruct_magnetic_picks(self): sys.stdout.flush() cnt = 0 for filename in magnetic_picks_filenames: cnt += 1 # Use pygplates to carry out the reconstruction print 'Reconstructing magnetic picks in {}'.format(filename) sys.stdout.flush() pygplates.reconstruct( filename, rotation_filenames, magnetic_picks_output_basename + '_{}.shp'.format(cnt), self.reconstruction_time, self.anchor_plate)
def write_trees_to_file(input_features, rotation_model, filename, reconstruction_time_range, time_step=1, polygon_type='static', root_feature_filename=None): reconstruction_times = np.arange(reconstruction_time_range[0], reconstruction_time_range[1]+time_step, time_step) tree_features = None root_centroid_features = [] for reconstruction_time in reconstruction_times: print 'working on time %0.2f Ma' % reconstruction_time reconstructed_polygons = [] if polygon_type is 'topological': pygplates.resolve_topologies(input_features, rotation_model, reconstructed_polygons, reconstruction_time) else: pygplates.reconstruct(input_features, rotation_model, reconstructed_polygons, reconstruction_time) uniq_plates_from_polygons = get_unique_plate_ids_from_reconstructed_features(reconstructed_polygons) reconstruction_tree = rotation_model.get_reconstruction_tree(reconstruction_time) chains = get_plate_chains(uniq_plates_from_polygons, reconstruction_tree) tree_features = create_hierarchy_features(chains, reconstructed_polygons, tree_features, valid_time=(reconstruction_time+time_step/2., reconstruction_time-time_step/2.)) if root_feature_filename is not None: polygon_centroids = get_polygon_centroids(reconstructed_polygons) root_plates = get_root_static_polygon_plate_ids(reconstruction_tree, uniq_plates_from_polygons) for root_plate in root_plates: p0 = polygon_centroids[root_plate] feature = pygplates.Feature() feature.set_geometry(pygplates.PointOnSphere(p0)) feature.set_name(str(root_plate)) feature.set_valid_time(reconstruction_time+time_step/2., reconstruction_time-time_step/2.) root_centroid_features.append(feature) tree_feature_collection = pygplates.FeatureCollection(tree_features) tree_feature_collection.write(filename) if root_feature_filename is not None: tree_feature_collection = pygplates.FeatureCollection(root_centroid_features) tree_feature_collection.write(root_feature_filename)
def GeneratePlateReferenceFrameXYZ(rotation_model, reconstruction_time, multipoint_feature_collection, InputGridFile): data = Dataset(InputGridFile, 'r') keys = [key for key in data.variables] lon = np.copy(data.variables[keys[0][:]]) lat = np.copy(data.variables[keys[1][:]]) [lon, lat] = np.meshgrid(lon, lat) Zg = data.variables['z'][:] ithetas = np.radians(90. - lat) iphis = np.radians(lon) irs = np.ones(np.shape(ithetas)) nodes = [] ixyzs = rtp2xyz(irs.ravel(), ithetas.ravel(), iphis.ravel()) tree = spatial.cKDTree(ixyzs, 16) with open('output', 'w') as output_file: # Create an interpolation object for this grid #f=RectBivariateSpline(lon,lat,data.variables['z'][:].T) # Reconstruct the multipoint features into a list of pygplates.ReconstructedFeatureGeometry's. reconstructed_feature_geometries = [] pygplates.reconstruct(multipoint_feature_collection, rotation_model, reconstructed_feature_geometries, reconstruction_time) print('num reconstructed multipoint geometries: %d' % len(reconstructed_feature_geometries)) for reconstructed_feature_geometry in reconstructed_feature_geometries: reconstructed_lon_points, reconstructed_lat_points, present_day_lat_lon_points = GetReconstructedMultipoint( reconstructed_feature_geometry) num_points = len(reconstructed_lon_points) # evaluate the current grid at the multipoint coordinates of the current feature #gridZr = f.ev(reconstructed_lon_points, reconstructed_lat_points) d, l = sampleOnSphere(lat, lon, Zg, np.array(reconstructed_lat_points), np.array(reconstructed_lon_points), tree=tree) gridZr = Zg.ravel()[l] # append the interpolated points as lon,lat,Z triples to an ascii file for point_index in range(0, num_points): pdp = present_day_lat_lon_points[point_index] output_file.write('%f %f %f\n' % (pdp[1], pdp[0], gridZr[point_index]))
def add_reconstructed_points_to_xyz(points_file, rotation_model, reconstruction_time, zval, mask_file=None): reconstructed_points = [] pygplates.reconstruct(points_file, rotation_model, reconstructed_points, reconstruction_time) #mask_file = './OrogenMasks.gpml' mask_file = None if mask_file is not None: reconstructed_masks = [] pygplates.reconstruct(mask_file, rotation_model, reconstructed_masks, reconstruction_time) for reconstructed_point in reconstructed_points: for reconstructed_mask in reconstructed_masks: if reconstructed_mask.get_reconstructed_geometry( ).is_point_in_polygon( reconstructed_point.get_reconstructed_geometry( ).get_centroid()): reconstructed_point.get_feature().set_name( reconstructed_mask.get_feature().get_name()) point_array = [] zval_array = [] for reconstructed_point in reconstructed_points: feature_coordinates = reconstructed_point.get_reconstructed_geometry( ).to_lat_lon_array() point_array.append(feature_coordinates) #if reconstructed_point.get_feature().get_feature_type() == pygplates.FeatureType.create_gpml('OrogenicBelt'): if reconstructed_point.get_feature().get_name() == 'OrogenicBelt': zval_array.append( np.ones((feature_coordinates.shape[0], 1)) * zval * 3) elif reconstructed_point.get_feature().get_name() == 'Cordillera': zval_array.append( np.ones((feature_coordinates.shape[0], 1)) * zval * 2) else: zval_array.append( np.ones((feature_coordinates.shape[0], 1)) * zval) xy_array = np.vstack(point_array) xyz_array = np.hstack((xy_array, np.vstack(zval_array))) return xyz_array
def group_features_by_motion(features, rotation_model, time, delta_time=1, plot=False): # given a list of features, a rotation model and a time range, # this function will make a list of all the plate_ids based on the # features, then determine groups of those plate ids within which # there is no relative motion between the plates during the specified # time range rps = [] pygplates.reconstruct(features, rotation_model, rps, time) pids = [] for rp in rps: pids.append(rp.get_feature().get_reconstruction_plate_id()) pg_pids = list(set(pids)) plate_group_lists = get_plate_motion_groups(pg_pids, rotation_model, time, delta_time) #print 'Number of groups is %d' % len(plate_group_lists) #for plate_group in plate_group_lists: # print plate_group if plot: cmap = plt.get_cmap('hsv') colors = cmap(np.linspace(0, 1, len(plate_group_lists))) plt.figure(figsize=(20, 9)) for rp in rps: for (plate_group, color) in zip(plate_group_lists, colors): if rp.get_feature().get_reconstruction_plate_id( ) in plate_group: plt.plot( rp.get_reconstructed_geometry().to_lat_lon_array()[:, 1], rp.get_reconstructed_geometry().to_lat_lon_array()[:, 0], color=color) plt.show() return plate_group_lists
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 run_grid_pnp(recon_time, points, spatial_tree_of_uniform_recon_points, polygons, rotation_model, distance_threshold_radians=2): reconstructed_polygons = [] pygplates.reconstruct(polygons, rotation_model, reconstructed_polygons, recon_time) rpolygons = [] for polygon in reconstructed_polygons: if polygon.get_reconstructed_geometry(): rpolygons.append(polygon.get_reconstructed_geometry()) res1 = find_closest_geometries_to_points_using_points_spatial_tree( points, spatial_tree_of_uniform_recon_points, rpolygons, distance_threshold_radians=distance_threshold_radians, geometries_are_solid=False) distance_to_polygon_boundary = np.array(list(zip(*res1))[0]) # Make a copy of list of distances. distance_to_polygon = list(distance_to_polygon_boundary) # Set distance to zero for any points inside a polygon (leave other points unchanged). res2 = points_in_polygons.find_polygons_using_points_spatial_tree( points, spatial_tree_of_uniform_recon_points, rpolygons) for point_index, rpolygon in enumerate(res2): # If not inside any polygons then result will be None. if rpolygon: distance_to_polygon[point_index] = 0.0 distance_to_polygon = np.array(distance_to_polygon) return distance_to_polygon, distance_to_polygon_boundary
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 create_gmt(model, time, proj, anchor_plate_id, tmp_dir,cnt=0,fmt='png'): data = get_reconstruction_model_dict(model) shp_path = settings.MODEL_STORE_DIR+model+'/'+data['Coastlines'] input_rotation_filename = [] for f in data['RotationFile']: input_rotation_filename.append((settings.MODEL_STORE_DIR+model+ '/'+f)) output_coastlines_filename = tmp_dir+'/coastlines.gmt' pygplates.reconstruct( shp_path, input_rotation_filename, output_coastlines_filename, int(time), int(anchor_plate_id)) #proj = '-JX20c/10c' if proj.lower() == 'robinson': projc = '-JN20c' elif proj.lower() == 'mollweide': projc = '-JW20c' else: projc = '-JQ20c' file_base_name = 'img-{:04d}'.format(cnt) os.system('gmt psbasemap -R-180/180/-90/90 {0} -K -Bafg -B+t\"{2}Ma\" > {1}/{3}.ps'.format(projc, tmp_dir, time, file_base_name)) os.system('gmt psxy -Rd {0} -W0.25p,grey10 -K -O -m {1}/coastlines.gmt -V >> {1}/{2}.ps'.format(projc, tmp_dir, file_base_name)) os.system('gmt psclip /usr/src/clip.txt -Rd {0} -O -V >> {1}/{2}.ps'.format(projc,tmp_dir, file_base_name)) os.system('cd {0} && gmt psconvert {0}/{1}.ps -A -E240 -Tg -P'.format(tmp_dir,file_base_name)) try: with open(tmp_dir+'/{0}.png'.format(file_base_name), "rb") as image_file: if fmt == 'base64': response = HttpResponse('data:image/png;base64,' + urllib.parse.quote(base64.b64encode(image_file.read()))) else: response = HttpResponse(image_file.read(),content_type='image/png') response['Access-Control-Allow-Origin'] = '*' return response except Exception as e: return HttpResponseServerError(str(e))
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 = [] for reconstructed_feature_geometry in coastline_reconstructed_feature_geometries: polygons.append( reconstructed_feature_geometry.get_reconstructed_geometry()) polygon_features.append(reconstructed_feature_geometry.get_feature()) # Create uniform lat/lon distribution of points.
def reconstruct_continent_ocean_boundaries(self): # Use pygplates to carry out the reconstruction pygplates.reconstruct(cob_filename, rotation_filenames, cob_output_basename + '.shp', self.reconstruction_time, self.anchor_plate)
def reconstruct_raster_stage(static_polygon_features, rotation_model, time_from, time_to, uniform_recon_points, spatial_tree_of_uniform_recon_points, anchor_plate_id=0): print 'Reconstruct static polygons...' # Reconstruct the multipoint feature. recon_static_polygon_features = [] pygplates.reconstruct(static_polygon_features, rotation_model, recon_static_polygon_features, time_to, anchor_plate_id=anchor_plate_id) # Extract the polygons and plate IDs from the reconstructed static polygons. recon_static_polygons = [] recon_static_polygon_plate_ids = [] for recon_static_polygon_feature in recon_static_polygon_features: recon_plate_id = recon_static_polygon_feature.get_feature( ).get_reconstruction_plate_id() recon_polygon = recon_static_polygon_feature.get_reconstructed_geometry( ) recon_static_polygon_plate_ids.append(recon_plate_id) recon_static_polygons.append(recon_polygon) print 'Find static polygons...' # Find the reconstructed static polygon (plate IDs) containing the uniform (reconstructed) points. # # The order (and length) of 'recon_point_plate_ids' matches the order (and length) of 'uniform_recon_points'. # Points outside all static polygons return a value of None. recon_point_plate_ids = points_in_polygons.find_polygons_using_points_spatial_tree( uniform_recon_points, spatial_tree_of_uniform_recon_points, recon_static_polygons, recon_static_polygon_plate_ids) print 'Group by polygons...' # Group recon points with plate IDs so we can later create one multipoint per plate. recon_points_grouped_by_plate_id = {} for point_index, point_plate_id in enumerate(recon_point_plate_ids): # Reject any points outside all reconstructed static polygons. if point_plate_id is None: continue # Add empty list to dict if first time encountering plate ID. if point_plate_id not in recon_points_grouped_by_plate_id: recon_points_grouped_by_plate_id[point_plate_id] = [] # Add to list of points associated with plate ID. recon_point = uniform_recon_points[point_index] recon_points_grouped_by_plate_id[point_plate_id].append(recon_point) print 'Reverse reconstruct points...' # Reconstructed points. recon_point_lons = [] recon_point_lats = [] # Present day points associated with reconstructed points. point_lons = [] point_lats = [] # Create a multipoint feature for each plate ID and reverse-reconstruct it to get present-day points. # # Iterate over key/value pairs in dictionary. for plate_id, recon_points_in_plate in recon_points_grouped_by_plate_id.iteritems( ): # Reverse reconstructing a multipoint is much faster than individually reverse-reconstructing points. multipoint_feature = pygplates.Feature() multipoint_feature.set_geometry( pygplates.MultiPointOnSphere(recon_points_in_plate)) multipoint_feature.set_reconstruction_plate_id(plate_id) # Reverse reconstruct the multipoint feature. pygplates.reverse_reconstruct(multipoint_feature, rotation_model, time_to, anchor_plate_id=anchor_plate_id) #Forward reconstruct multipoint to multipoint_at_from_time = [] pygplates.reconstruct(multipoint_feature, rotation_model, multipoint_at_from_time, time_from, anchor_plate_id=anchor_plate_id) # Extract reverse-reconstructed geometry. multipoint = multipoint_at_from_time[0].get_reconstructed_geometry() # Collect present day and associated reconstructed points. for point_index, point in enumerate(multipoint): lat, lon = point.to_lat_lon() point_lons.append(lon) point_lats.append(lat) recon_point = recon_points_in_plate[point_index] recon_lat, recon_lon = recon_point.to_lat_lon() recon_point_lons.append(recon_lon) recon_point_lats.append(recon_lat) print 'Sample present-day grid...' # Query present-day grid using present-day points. # # TODO: Note sure what happens in regions where there's no data in grid (need to ignore those points). #data = data_grid.ev(point_lons, point_lats) #data = [1.0] * len(recon_point_lons) #data = sample_grid_using_scipy(point_lons,point_lats,grdfile) return recon_point_lons, recon_point_lats, point_lons, point_lats
def GenerateReconstructedDeltaXYZ(rotation_model, reconstruction_time1, reconstruction_time2, multipoint_feature_collection, InputGridFile1, InputGridFile2, force_plate_frame): data1 = Dataset(InputGridFile1, 'r') data2 = Dataset(InputGridFile2, 'r') keys = [key for key in data1.variables] lon = np.copy(data1.variables[keys[0][:]]) lat = np.copy(data1.variables[keys[1][:]]) # lon = np.copy(data1.variables['x'][:]) # lat = np.copy(data1.variables['y'][:]) #except: # lon = np.copy(data1.variables['lon'][:]) # lat = np.copy(data1.variables['lat'][:]) [lon, lat] = np.meshgrid(lon, lat) Zg1 = data1.variables['z'][:] Zg2 = data2.variables['z'][:] ithetas = np.radians(90. - lat) iphis = np.radians(lon) irs = np.ones(np.shape(ithetas)) nodes = [] ixyzs = rtp2xyz(irs.ravel(), ithetas.ravel(), iphis.ravel()) tree = spatial.cKDTree(ixyzs, 16) reconstruction_time_mid = 0.5 * (reconstruction_time1 + reconstruction_time2) with open('output', 'w') as output_file: # Create interpolation objects for these grids #f1=RectBivariateSpline(data1.variables['lon'][:],data1.variables['lat'][:],data1.variables['z'][:].T) #f2=RectBivariateSpline(data2.variables['lon'][:],data2.variables['lat'][:],data2.variables['z'][:].T) # Reconstruct the multipoint features into a list of pygplates.ReconstructedFeatureGeometry's. reconstructed_feature_geometries1 = [] reconstructed_feature_geometries2 = [] reconstructed_feature_geometries_mid = [] pygplates.reconstruct(multipoint_feature_collection, rotation_model, reconstructed_feature_geometries1, reconstruction_time1) pygplates.reconstruct(multipoint_feature_collection, rotation_model, reconstructed_feature_geometries2, reconstruction_time2) pygplates.reconstruct(multipoint_feature_collection, rotation_model, reconstructed_feature_geometries_mid, reconstruction_time_mid) print('num reconstructed multipoint geometries: %d' % len(reconstructed_feature_geometries1)) for reconstructed_feature_geometry_index in range( 0, len(reconstructed_feature_geometries1)): reconstructed_feature_geometry1 = reconstructed_feature_geometries1[ reconstructed_feature_geometry_index] reconstructed_feature_geometry2 = reconstructed_feature_geometries2[ reconstructed_feature_geometry_index] reconstructed_feature_geometry_mid = reconstructed_feature_geometries_mid[ reconstructed_feature_geometry_index] reconstructed_lon_points1, reconstructed_lat_points1, present_day_lat_lon_points1 = \ GetReconstructedMultipoint(reconstructed_feature_geometry1) reconstructed_lon_points2, reconstructed_lat_points2, present_day_lat_lon_points2 = \ GetReconstructedMultipoint(reconstructed_feature_geometry2) reconstructed_lon_points_mid, reconstructed_lat_points_mid, present_day_lat_lon_points_mid = \ GetReconstructedMultipoint(reconstructed_feature_geometry_mid) num_points = len(reconstructed_lon_points1) # evaluate the current grids at the multipoint coordinates of the current feature #gridZr1 = f1.ev(reconstructed_lon_points1, reconstructed_lat_points1) #gridZr2 = f2.ev(reconstructed_lon_points2, reconstructed_lat_points2) #gridZr1 = sample_grid_using_kdtree(np.array(reconstructed_lon_points1), np.array(reconstructed_lat_points1), InputGridFile1) #gridZr2 = sample_grid_using_kdtree(np.array(reconstructed_lon_points2), np.array(reconstructed_lat_points2), InputGridFile2) d, l = sampleOnSphere(lat, lon, Zg1, np.array(reconstructed_lat_points1), np.array(reconstructed_lon_points1), tree=tree) gridZr1 = Zg1.ravel()[l] d, l = sampleOnSphere(lat, lon, Zg2, np.array(reconstructed_lat_points1), np.array(reconstructed_lon_points1), tree=tree) gridZr2 = Zg2.ravel()[l] #print gridZr1 # append the interpolated points as lon,lat,Z triples to an ascii file for point_index in range(0, num_points): delta = (gridZr1[point_index] - gridZr2[point_index]) / ( reconstruction_time2 - reconstruction_time1) if force_plate_frame: output_lon = present_day_lat_lon_points_mid[point_index][1] output_lat = present_day_lat_lon_points_mid[point_index][0] else: output_lon = reconstructed_lon_points_mid[point_index] output_lat = reconstructed_lat_points_mid[point_index] output_file.write('%f %f %f\n' % (output_lon, output_lat, delta))
def reconstruct_fracture_zones(self): # Use pygplates to carry out the reconstruction print 'Reconstructing fracture zones...' pygplates.reconstruct(fracture_zones_filename, rotation_filenames, fracture_zones_output_basename + '.shp', self.reconstruction_time, self.anchor_plate)
print now( ), 'frame_change_pygplates: Create RectBivariateSpline of input grid' # Create an interpolation object for this grid f = RectBivariateSpline(input_grid.variables['lon'][:], input_grid.variables['lat'][:], input_grid.variables['z'][:].T) # Reconstruct the multipoint features into a list of pygplates.ReconstructedFeatureGeometry's. reconstructed_feature_geometries = [] print now( ), 'frame_change_pygplates: pygplates.reconstruct multipoint_feature_collection' pygplates.reconstruct(multipoint_feature_collection, rotation_model, reconstructed_feature_geometries, reconstruction_time) print now( ), 'frame_change_pygplates: num reconstructed multipoint geometries: %d' % len( reconstructed_feature_geometries) # loop over RFGs for reconstructed_feature_geometry in reconstructed_feature_geometries: # Get the recon positions reconstructed_lon_points, reconstructed_lat_points, present_day_lat_lon_points = GetReconstructedMultipoint( reconstructed_feature_geometry) num_points = len(reconstructed_lon_points) # too verbose ?
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. # This does not remove partially overlapping geometries, etc. _remove_duplicate_reconstructed_feature_geometries(proximity_reconstructed_feature_geometries) # Iterate over reconstructed geometries and add up their segment lengths. for proximity_reconstructed_feature_geometry in proximity_reconstructed_feature_geometries: proximity_reconstructed_geometry = proximity_reconstructed_feature_geometry.get_reconstructed_geometry() try: length_in_kms += proximity_reconstructed_geometry.get_arc_length() * pygplates.Earth.mean_radius_in_kms except AttributeError: # Only polylines and polygons have the 'get_arc_length()' method. # Skip points and multipoints... continue
def get_static_polygons(request): """ http GET request to retrieve reconstructed static polygons **usage** <http-address-to-gws>/reconstruct/static_polygons/plate_id=\ *anchor_plate_id*\&time=\ *reconstruction_time*\&model=\ *reconstruction_model* **parameters:** *anchor_plate_id* : integer value for reconstruction anchor plate id [default=0] *time* : time for reconstruction [required] *model* : name for reconstruction model [defaults to default model from web service settings] **returns:** json containing reconstructed coastline features """ anchor_plate_id = request.GET.get('pid', 0) time = request.GET.get('time', 0) model = request.GET.get('model',settings.MODEL_DEFAULT) wrap = True central_meridian = 0 if 'central_meridian' in request.GET: try: central_meridian = float(request.GET['central_meridian']) wrap = True except: print('Invalid central meridian.') avoid_map_boundary = False if 'avoid_map_boundary' in request.GET: avoid_map_boundary = True 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']]) reconstructed_polygons = [] pygplates.reconstruct( str('%s/%s/%s' % (settings.MODEL_STORE_DIR,model,model_dict['StaticPolygons'])), rotation_model, reconstructed_polygons, float(time), anchor_plate_id=anchor_plate_id) data = process_reconstructed_polygons(reconstructed_polygons, wrap, central_meridian, avoid_map_boundary) 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)
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 motion_path(request): """ http GET request to retrieve reconstructed static polygons **usage** <http-address-to-gws>/reconstruct/motion_path/seedpoints=\ *points*\×pec=\ *time_list*\&fixplate=\ *fixed_plate_id*\&movplate=\ *moving_plate_id*\&time=\ *reconstruction_time*\&model=\ *reconstruction_model* :param seedpoints: integer value for reconstruction anchor plate id [required] :param timespec: specification for times for motion path construction, in format 'mintime,maxtime,increment' [defaults to '0,100,10'] :param time: time for reconstruction [default=0] :param fixplate: integer plate id for fixed plate [default=0] :param movplate: integer plate id for moving plate [required] :param model: name for reconstruction model [defaults to default model from web service settings] :returns: json containing reconstructed motion path features """ seedpoints = request.GET.get('seedpoints', None) times = request.GET.get('timespec', '0,100,10') reconstruction_time = request.GET.get('time', 0) RelativePlate = request.GET.get('fixplate', 0) MovingPlate = request.GET.get('movplate', None) model = request.GET.get('model',settings.MODEL_DEFAULT) points = [] if seedpoints: ps = seedpoints.split(',') if len(ps)%2==0: for lat,lon in zip(ps[1::2], ps[0::2]): points.append((float(lat),float(lon))) seed_points_at_digitisation_time = pygplates.MultiPointOnSphere(points) if times: ts = times.split(',') if len(ts)==3: times = np.arange(float(ts[0]),float(ts[1])+0.1,float(ts[2])) 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']]) # Create the motion path feature digitisation_time = 0 #seed_points_at_digitisation_time = pygplates.MultiPointOnSphere([SeedPoint]) motion_path_feature = pygplates.Feature.create_motion_path( seed_points_at_digitisation_time, times = times, valid_time=(2000, 0), relative_plate=int(RelativePlate), reconstruction_plate_id = int(MovingPlate)) # Create the shape of the motion path #reconstruction_time = 0 reconstructed_motion_paths = [] pygplates.reconstruct( motion_path_feature, rotation_model, reconstructed_motion_paths, float(reconstruction_time), reconstruct_type=pygplates.ReconstructType.motion_path) data = {"type": "FeatureCollection"} data["features"] = [] for reconstructed_motion_path in reconstructed_motion_paths: Dist = [] for segment in reconstructed_motion_path.get_motion_path().get_segments(): Dist.append(segment.get_arc_length()*pygplates.Earth.mean_radius_in_kms) feature = {"type": "Feature"} feature["geometry"] = {} feature["geometry"]["type"] = "LineString" #### NOTE CODE TO FLIP COORDINATES TO feature["geometry"]["coordinates"] = [(lon,lat) for lat,lon in reconstructed_motion_path.get_motion_path().to_lat_lon_list()] feature["geometry"]["distance"] = Dist 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_points(request): """ http GET request to reconstruct points **usage** <http-address-to-gws>/reconstruct/reconstruct_points/points=\ *points*\&plate_id=\ *anchor_plate_id*\&time=\ *reconstruction_time*\&model=\ *reconstruction_model* **parameters:** *points* : list of points long,lat comma separated coordinates of points to be reconstructed [Required] *anchor_plate_id* : integer value for reconstruction anchor plate id [default=0] *time* : time for reconstruction [required] *model* : name for reconstruction model [defaults to default model from web service settings] **returns:** json list of long,lat reconstructed coordinates """ if request.method == 'POST': params = request.POST elif request.method == 'GET': params = request.GET else: return HttpResponseBadRequest('Unrecognized request type') points = params.get('points', None) anchor_plate_id = params.get('pid', 0) time = params.get('time', None) model = params.get('model',settings.MODEL_DEFAULT) return_null_points = True if 'return_null_points' in params else False return_feature_collection = True if 'fc' in params else False is_reverse = True if 'reverse' in params else False timef=0.0 if not time: return HttpResponseBadRequest('The "time" parameter cannot be empty.') else: 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)) 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'])) # create point features from input coordinates p_index=0 point_features = [] if points: ps = points.split(',') if len(ps)%2==0: try: 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_feature.set_name(str(p_index)) point_features.append(point_feature) p_index += 1 except pygplates.InvalidLatLonError as e: return HttpResponseBadRequest('Invalid longitude or latitude ({0}).'.format(e)) else: return HttpResponseBadRequest('The longitude and latitude should come in pairs ({0}).'.format(points)) else: return HttpResponseBadRequest('The "points" parameter is missing.') # assign plate-ids to points using static polygons partition_time = timef if is_reverse else 0. #LOOK HERE !!!! #it seems when the partition_time is not 0 #the returned assigned_point_features contains reverse reconstructed present-day geometries. #so, when doing reverse reconstruct, do not reverse reconstruct again later. 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], reconstruction_time = partition_time ) # reconstruct the points assigned_point_feature_collection = pygplates.FeatureCollection(assigned_point_features) reconstructed_feature_geometries = [] if not is_reverse: pygplates.reconstruct( assigned_point_feature_collection, rotation_model, reconstructed_feature_geometries, timef, anchor_plate_id=anchor_plate_id) rfgs = p_index*[None] for rfg in reconstructed_feature_geometries: rfgs[int(rfg.get_feature().get_name())] = rfg assigned_fc = p_index*[None] for f in assigned_point_feature_collection: assigned_fc[int(f.get_name())] = f # prepare the response to be returned if not return_feature_collection: ret='{"type":"MultiPoint","coordinates":[' for idx in range(p_index): lon = None lat = None if not is_reverse and rfgs[idx]: lon = rfgs[idx].get_reconstructed_geometry().to_lat_lon()[1] lat = rfgs[idx].get_reconstructed_geometry().to_lat_lon()[0] elif is_reverse and assigned_fc[idx]: lon = assigned_fc[idx].get_geometry().to_lat_lon()[1] lat = assigned_fc[idx].get_geometry().to_lat_lon()[0] if lon is not None and lat is not None: ret+='[{0:5.2f},{1:5.2f}],'.format(lon, lat) elif return_null_points: ret+='null,' else: ret='{"type":"FeatureCollection","features":[' for idx in range(p_index): lon = None lat = None begin_time = None end_time = None if not is_reverse and rfgs[idx]: lon = rfgs[idx].get_reconstructed_geometry().to_lat_lon()[1] lat = rfgs[idx].get_reconstructed_geometry().to_lat_lon()[0] elif is_reverse and assigned_fc[idx]: lon = assigned_fc[idx].get_geometry().to_lat_lon()[1] lat = assigned_fc[idx].get_geometry().to_lat_lon()[0] if assigned_fc[idx]: valid_time = assigned_fc[idx].get_valid_time(None) if valid_time: begin_time, end_time = valid_time ret+='{"type":"Feature","geometry":' if lon is not None and lat is not None: ret+='{'+'"type":"Point","coordinates":[{0:5.2f},{1:5.2f}]'.format(lon, lat)+'},' else: ret+='null,' if begin_time is not None and end_time is not None: #write out begin and end time if begin_time == pygplates.GeoTimeInstant.create_distant_past(): begin_time = '"distant past"' if end_time == pygplates.GeoTimeInstant.create_distant_future(): end_time = '"distant future"' ret+='"properties":{'+'"valid_time":[{0},{1}]'.format(begin_time,end_time)+'}},' else: ret+='"properties":{}'+'},' ret=ret[0:-1] ret+=']}' #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