예제 #1
0
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
예제 #2
0
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
예제 #3
0
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
예제 #4
0
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
예제 #5
0
 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)
예제 #6
0
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)
예제 #7
0
    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)
예제 #8
0
 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)
예제 #9
0
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
예제 #10
0
 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)
예제 #11
0
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)
예제 #12
0
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]))
예제 #13
0
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
예제 #15
0
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')
예제 #16
0
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
예제 #17
0
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
예제 #18
0
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.
예제 #20
0
 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)
예제 #21
0
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
예제 #22
0
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))
예제 #23
0
 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
예제 #26
0
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
예제 #27
0
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)
예제 #28
0
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
예제 #29
0
def motion_path(request):
    """
    http GET request to retrieve reconstructed static polygons

    **usage**
    
    <http-address-to-gws>/reconstruct/motion_path/seedpoints=\ *points*\&timespec=\ *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
예제 #30
0
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