def diffrot_velocity(coordinates,omega_eq,omega_pole,R_pole,M):
    """
    Calculate the velocity vector of every surface element.

    @param coordinates: polar coordinates of stellar surface (phi,theta,radius)
    make sure the radius is in SI units!
    @type coordinates: 3xN array
    @param omega_eq: equatorial angular velocity (as a fraction of the critical one)
    @type omega_eq: float
    @param omega_pole: polar angular velocity (as a fraction of the critical one)
    @type omega_pole: float
    @param R_pole: polar radius in solar radii
    @type R_pole: float
    @param M: stellar mass in solar mass
    @type M: float
    @return: velocity vectors of all surface elements
    @rtype 3xN array
    """
    #-- angular velocity of every surface element
    Omega_crit = critical_angular_velocity(M,R_pole)
    phi,theta,radius = coordinates
    omega_local = diffrot_law(omega_eq,omega_pole,theta)*Omega_crit
    #-- direction of local angular velocity in Cartesian coordinates (directed in upwards z)
    omega_local_vec = np.array([np.zeros_like(omega_local),np.zeros_like(omega_local),omega_local]).T

    x,y,z = vectors.spher2cart_coord(radius,phi,theta)
    surface_element = np.array([x,y,z]).T

    velo_local = np.array([np.cross(ielement,iomega_local_vec) for ielement,iomega_local_vec in zip(surface_element,omega_local_vec)]).T
    return velo_local
Exemplo n.º 2
0
def diffrot_velocity(coordinates,omega_eq,omega_pole,R_pole,M):
    """
    Calculate the velocity vector of every surface element.
    
    @param coordinates: polar coordinates of stellar surface (phi,theta,radius)
    make sure the radius is in SI units!
    @type coordinates: 3xN array
    @param omega_eq: equatorial angular velocity (as a fraction of the critical one)
    @type omega_eq: float
    @param omega_pole: polar angular velocity (as a fraction of the critical one)
    @type omega_pole: float
    @param R_pole: polar radius in solar radii
    @type R_pole: float
    @param M: stellar mass in solar mass
    @type M: float
    @return: velocity vectors of all surface elements
    @rtype 3xN array
    """
    #-- angular velocity of every surface element
    Omega_crit = critical_angular_velocity(M,R_pole)
    phi,theta,radius = coordinates
    omega_local = diffrot_law(omega_eq,omega_pole,theta)*Omega_crit
    #-- direction of local angular velocity in Cartesian coordinates (directed in upwards z)
    omega_local_vec = np.array([np.zeros_like(omega_local),np.zeros_like(omega_local),omega_local]).T
    
    x,y,z = vectors.spher2cart_coord(radius,phi,theta)
    surface_element = np.array([x,y,z]).T

    velo_local = np.array([np.cross(ielement,iomega_local_vec) for ielement,iomega_local_vec in zip(surface_element,omega_local_vec)]).T
    return velo_local
Exemplo n.º 3
0
def surface_normals(r,phi,theta,grid,gtype='spher'):
    """
    Numerically compute surface normals of a grid (in absence of analytical alternative).
    
    Also computes the surface elements, making L{surface_elements} obsolete.
    """
    if gtype=='spher':
        raise NotImplementedError
    elif gtype=='delaunay':
        raise NotImplementedError
    elif gtype=='triangular':
        #-- compute the angle between the surface normal and the radius vector
        x,y,z = vectors.spher2cart_coord(r,phi,theta)
        
        centers = np.zeros((len(grid.convex_hull),3))
        normals = np.zeros((len(grid.convex_hull),3))
        sizes = np.zeros(len(grid.convex_hull))
        
        #vertx,verty,vertz = points.T

        #-- compute centers,normals and sizes
        for i,indices in enumerate(grid.convex_hull):
            #-- center is triangle's barycenter
            centers[i] = [x[indices].sum()/3,y[indices].sum()/3,z[indices].sum()/3]
            #-- size is size of triangle
            a = sqrt((x[indices[0]]-x[indices[1]])**2 + (y[indices[0]]-y[indices[1]])**2 + (z[indices[0]]-z[indices[1]])**2)
            b = sqrt((x[indices[0]]-x[indices[2]])**2 + (y[indices[0]]-y[indices[2]])**2 + (z[indices[0]]-z[indices[2]])**2)
            c = sqrt((x[indices[1]]-x[indices[2]])**2 + (y[indices[1]]-y[indices[2]])**2 + (z[indices[1]]-z[indices[2]])**2)
            s = 0.5*(a+b+c)
            sizes[i] = sqrt( s*(s-a)*(s-b)*(s-c))
            #-- normal is cross product of two sides
            side1 = [x[indices[1]]-x[indices[0]],y[indices[1]]-y[indices[0]],z[indices[1]]-z[indices[0]]]
            side2 = [x[indices[2]]-x[indices[0]],y[indices[2]]-y[indices[0]],z[indices[2]]-z[indices[0]]]
            normals[i] = np.cross(side1,side2)
        
        #-- make sure the normal is pointed outwards
        normal_r,normal_phi,normal_theta = vectors.cart2spher(centers.T,normals.T)
        normal_r = np.abs(normal_r)
        centers_sph = vectors.cart2spher_coord(*centers.T)
        normals = np.array(vectors.spher2cart(centers_sph,(normal_r,normal_phi,normal_theta)))
        
        #-- normalise and compute angles
        normals_T = normals.T
        normals = normals_T / vectors.norm(normals_T)
        #cos_gamma = vectors.cos_angle(a,normals)
        print centers.shape,sizes.shape,normals.shape
        return centers, sizes, normals#, cos_gamma
Exemplo n.º 4
0
           (theta + ksi_theta.real),\
           (phi + ksi_phi.real),\
           (teff + (delta_T*rad_part*teff).real),\
           np.log10(gravity+(delta_g*rad_part*gravity).real)+2


#}

if __name__ == "__main__":
    from ivs.roche import local
    from ivs.coordinates import vectors
    from enthought.mayavi import mlab
    from divers import multimedia
    theta, phi = local.get_grid(50, 25, gtype='triangular')
    r = np.ones_like(theta)
    x, y, z = vectors.spher2cart_coord(r, phi, theta)
    points = np.array([x, y, z]).T
    grid = Delaunay(points)
    #keep = phi>pi
    #theta,phi = theta[keep],phi[keep]
    l, m = 2, 2
    asl = 0.01

    for k in [0, 1., 2.]:
        for l in range(1, 5):
            for m in range(0, l + 1, 1):
                mlab.figure(size=(1000, 800))
                mlab.gcf().scene.disable_render = True
                if l == 0 or l == 1:
                    asl = 0.1
                else:
Exemplo n.º 5
0
def project(star,
            view_long=(0, 0, 0),
            view_lat=(pi / 2, 0, 0),
            photband='OPEN.BOL',
            only_visible=False,
            plot_sort=False,
            scale_factor=1.):
    """
    Project and transform coordinates and vectors to align with the line-of-sight.

    Parameter C{star} should be a record array containing fields 'teff','gravx',
    'gravy','gravz','areas','vx','vy','vz'

    and either you suply ('r','theta','phi') or ('x','y','z')

    The XY direction is then the line-of-sight, and the YZ plane is the plane
    of the sky.

    An extra column 'projflux' and 'eyeflux' will be added. Projected flux
    takes care of limb darkening, and projected surface area. Eye flux only
    takes care of limbdarkening, and should only be used for plotting reasons.

    view_long[0] of 0 means looking in the XY line, pi means looking in the YX line.
    view_lat[0] of pi/2 means edge on, 0 or pi is pole-on.

    This function updates all Cartesian coordinates present in the star, but not
    the polar coordinates! The projected fluxes are added as a field 'projflux'
    to the returned record array.

    If you set 'only_visible' to True, only the information on the visible parts
    of the star will be contained.

    If you set 'plot_sort' to True, the arrays will be returned in a sorted order,
    where the areas at the back come first. This is especially handy for plotting.

    @parameters star: record array containing all necessary information on the
    star
    @type star: numpy record array
    @parameter view_long: longitude viewing angle (radians) and coordinate zeropoint
    @type view_long: tuple floats  (radians,x,y)
    @parameter view_lat: inclination viewing angle (radians) and coordinate zeropoint
    @type view_lat: tuple floats (radians,x,z)
    @parameter photband: photometric passband
    @type photband: string
    @parameter only_visible: flag to return only information on visible surface elements
    @type only_visible: boolean
    @parameter plot_sort: flag to sort the surface elements from back to front
    @type plot_sort: boolean
    """
    myshape = star['gravx'].shape
    gravx, gravy, gravz = np.array(
        [star['gravx'].ravel(), star['gravy'].ravel(), star['gravz'].ravel()])
    areas = star['areas'].ravel()
    teff = star['teff'].ravel()
    vx, vy, vz = star['vx'].ravel(), star['vy'].ravel(), star['vz'].ravel()
    #-- if 'x' is not in the star's record array, we assume the polar coordinates
    #   are in there and convert them to Cartesian coordinates
    if not 'x' in star.dtype.names:
        x, y, z = vectors.spher2cart_coord(star['r'].ravel(),
                                           star['phi'].ravel(),
                                           star['theta'].ravel())
    else:
        x, y, z = star['x'].ravel(), star['y'].ravel(), star['z'].ravel(),

    #-- first we rotate in the XY plane (only for surface coordinates is the
    #   coordinate zeropoint important, the rest are vectors!):
    x, y = vectors.rotate(x, y, view_long[0], x0=view_long[1], y0=view_long[2])
    gravx, gravy = vectors.rotate(gravx, gravy, view_long[0])
    vx, vy = vectors.rotate(vx, vy, view_long[0])
    #-- then we rotate in the YZ plane:
    if view_lat[0] != pi / 2:
        rot_i = -(pi / 2 - view_lat[0])
        x, z = vectors.rotate(x, z, rot_i)
        gravx, gravz = vectors.rotate(gravx, gravz, rot_i)
        vx, vz = vectors.rotate(vx, vz, rot_i)
    #-- ... and project the fluxes in the line of sight, which is now in the XY
    #   direction:
    view_vector = np.array([1., 0, 0])  #np.array([-sin(pi/2),0,-cos(pi/2)])
    grav_local = np.array([gravx, gravy, gravz])
    proj_flux, mus = projected_intensity(teff,
                                         grav_local,
                                         areas,
                                         view_vector,
                                         photband=photband)

    #-- we now construct a copy of the star record array with the changed
    #   coordinates
    new_star = star.copy()
    new_star['gravx'], new_star['gravy'], new_star[
        'gravz'] = gravx, gravy, gravz
    new_star['vx'], new_star['vy'], new_star['vz'] = vx, vy, vz
    if 'x' in star.dtype.names:
        new_star['x'], new_star['y'], new_star[
            'z'] = x * scale_factor, y * scale_factor, z * scale_factor
    else:
        new_star = pl.mlab.rec_append_fields(new_star, 'x', x * scale_factor)
        new_star = pl.mlab.rec_append_fields(new_star, 'y', y * scale_factor)
        new_star = pl.mlab.rec_append_fields(new_star, 'z', z * scale_factor)
    new_star = pl.mlab.rec_append_fields(new_star, 'projflux', proj_flux)
    new_star = pl.mlab.rec_append_fields(new_star, 'eyeflux',
                                         proj_flux / areas)
    new_star = pl.mlab.rec_append_fields(new_star, 'mu', mus)

    #-- clip visible areas and sort in plotting order if necessary
    if only_visible:
        new_star = new_star[-np.isnan(new_star['projflux'])]
    if plot_sort:
        new_star = new_star[np.argsort(new_star['x'])]
    return new_star
Exemplo n.º 6
0
def surface_elements(radius_and_mygrid, surface_normals_xyz, gtype='spher'):
    """
    Compute surface area of elements in a grid.

    theta,phi must be generated like mgrid(theta_range,phi_range)

    usually, the surfnormals are acquired via differentiation of a gravity potential,
    and is then equal to the *negative* of the local surface gravity.
    """
    (r, mygrid) = radius_and_mygrid
    (surfnormal_x, surfnormal_y, surfnormal_z) = surface_normals_xyz
    theta, phi = mygrid[:2]
    if gtype == 'spher':
        #-- compute the grid size at each location
        dtheta = theta[1:] - theta[:-1]
        dtheta = np.vstack([dtheta, dtheta[-1]])

        dphi = phi[:, 1:] - phi[:, :-1]
        dphi = np.column_stack([dphi, dphi[:, -1]])
        #-- compute the angle between the surface normal and the radius vector
        x, y, z = vectors.spher2cart_coord(r, phi, theta)

        a = np.array([x, y, z])
        b = np.array([surfnormal_x, surfnormal_y, surfnormal_z])

        cos_gamma = vectors.cos_angle(a, b)

        return r**2 * sin(theta) * dtheta * dphi / cos_gamma, cos_gamma

    elif gtype == 'delaunay':
        #-- compute the angle between the surface normal and the radius vector
        x, y, z = vectors.spher2cart_coord(r, phi, theta)
        a = np.array([x, y, z])
        b = np.array([surfnormal_x, surfnormal_y, surfnormal_z])
        cos_gamma = vectors.cos_angle(a, b)

        delaunay_grid = mygrid[2]

        sizes = np.zeros(len(delaunay_grid.convex_hull))
        points = delaunay_grid.points
        vertx, verty, vertz = points.T

        #from enthought.mayavi import mlab
        #mlab.figure()
        #mlab.triangular_mesh(vertx,verty,vertz,delaunay_grid.convex_hull,scalars=np.ones_like(vertx),colormap='gray',representation='wireframe')
        #mlab.points3d(x/r,y/r,z/r,scale_factor=0.02)

        centers = np.zeros((len(delaunay_grid.convex_hull), 3))
        for i, indices in enumerate(delaunay_grid.convex_hull):
            #centers[i] = [vertx[indices].sum()/3,verty[indices].sum()/3,vertz[indices].sum()/3]
            a = sqrt((vertx[indices[0]] - vertx[indices[1]])**2 +
                     (verty[indices[0]] - verty[indices[1]])**2 +
                     (vertz[indices[0]] - vertz[indices[1]])**2)
            b = sqrt((vertx[indices[0]] - vertx[indices[2]])**2 +
                     (verty[indices[0]] - verty[indices[2]])**2 +
                     (vertz[indices[0]] - vertz[indices[2]])**2)
            c = sqrt((vertx[indices[1]] - vertx[indices[2]])**2 +
                     (verty[indices[1]] - verty[indices[2]])**2 +
                     (vertz[indices[1]] - vertz[indices[2]])**2)
            s = 0.5 * (a + b + c)
            sizes[i] = sqrt(s * (s - a) * (s - b) * (s - c))

        #theta,phi = np.arccos(centers[:,2]),np.arctan2(centers[:,1],centers[:,0])+pi
        #mlab.points3d(centers[:,0],centers[:,1],centers[:,2],sizes,scale_factor=0.05,scale_mode='none',colormap='RdBu')
        #mlab.show()

        #pl.show()

        return sizes * r**2, cos_gamma
Exemplo n.º 7
0
def surface_normals(r, phi, theta, grid, gtype='spher'):
    """
    Numerically compute surface normals of a grid (in absence of analytical alternative).

    Also computes the surface elements, making L{surface_elements} obsolete.
    """
    if gtype == 'spher':
        raise NotImplementedError
    elif gtype == 'delaunay':
        raise NotImplementedError
    elif gtype == 'triangular':
        #-- compute the angle between the surface normal and the radius vector
        x, y, z = vectors.spher2cart_coord(r, phi, theta)

        centers = np.zeros((len(grid.convex_hull), 3))
        normals = np.zeros((len(grid.convex_hull), 3))
        sizes = np.zeros(len(grid.convex_hull))

        #vertx,verty,vertz = points.T

        #-- compute centers,normals and sizes
        for i, indices in enumerate(grid.convex_hull):
            #-- center is triangle's barycenter
            centers[i] = [
                x[indices].sum() / 3, y[indices].sum() / 3,
                z[indices].sum() / 3
            ]
            #-- size is size of triangle
            a = sqrt((x[indices[0]] - x[indices[1]])**2 +
                     (y[indices[0]] - y[indices[1]])**2 +
                     (z[indices[0]] - z[indices[1]])**2)
            b = sqrt((x[indices[0]] - x[indices[2]])**2 +
                     (y[indices[0]] - y[indices[2]])**2 +
                     (z[indices[0]] - z[indices[2]])**2)
            c = sqrt((x[indices[1]] - x[indices[2]])**2 +
                     (y[indices[1]] - y[indices[2]])**2 +
                     (z[indices[1]] - z[indices[2]])**2)
            s = 0.5 * (a + b + c)
            sizes[i] = sqrt(s * (s - a) * (s - b) * (s - c))
            #-- normal is cross product of two sides
            side1 = [
                x[indices[1]] - x[indices[0]], y[indices[1]] - y[indices[0]],
                z[indices[1]] - z[indices[0]]
            ]
            side2 = [
                x[indices[2]] - x[indices[0]], y[indices[2]] - y[indices[0]],
                z[indices[2]] - z[indices[0]]
            ]
            normals[i] = np.cross(side1, side2)

        #-- make sure the normal is pointed outwards
        normal_r, normal_phi, normal_theta = vectors.cart2spher(
            centers.T, normals.T)
        normal_r = np.abs(normal_r)
        centers_sph = vectors.cart2spher_coord(*centers.T)
        normals = np.array(
            vectors.spher2cart(centers_sph,
                               (normal_r, normal_phi, normal_theta)))

        #-- normalise and compute angles
        normals_T = normals.T
        normals = normals_T / vectors.norm(normals_T)
        #cos_gamma = vectors.cos_angle(a,normals)
        print(centers.shape, sizes.shape, normals.shape)
        return centers, sizes, normals  #, cos_gamma
Exemplo n.º 8
0
def project(star,view_long=(0,0,0),view_lat=(pi/2,0,0),photband='OPEN.BOL',
            only_visible=False,plot_sort=False,scale_factor=1.):
    """
    Project and transform coordinates and vectors to align with the line-of-sight.
    
    Parameter C{star} should be a record array containing fields 'teff','gravx',
    'gravy','gravz','areas','vx','vy','vz'
    
    and either you suply ('r','theta','phi') or ('x','y','z')
    
    The XY direction is then the line-of-sight, and the YZ plane is the plane
    of the sky.
    
    An extra column 'projflux' and 'eyeflux' will be added. Projected flux
    takes care of limb darkening, and projected surface area. Eye flux only
    takes care of limbdarkening, and should only be used for plotting reasons.
    
    view_long[0] of 0 means looking in the XY line, pi means looking in the YX line.
    view_lat[0] of pi/2 means edge on, 0 or pi is pole-on.
    
    This function updates all Cartesian coordinates present in the star, but not
    the polar coordinates! The projected fluxes are added as a field 'projflux'
    to the returned record array.
    
    If you set 'only_visible' to True, only the information on the visible parts
    of the star will be contained.
    
    If you set 'plot_sort' to True, the arrays will be returned in a sorted order,
    where the areas at the back come first. This is especially handy for plotting.
    
    @parameters star: record array containing all necessary information on the
    star
    @type star: numpy record array
    @parameter view_long: longitude viewing angle (radians) and coordinate zeropoint
    @type view_long: tuple floats  (radians,x,y)
    @parameter view_lat: inclination viewing angle (radians) and coordinate zeropoint
    @type view_lat: tuple floats (radians,x,z)
    @parameter photband: photometric passband
    @type photband: string
    @parameter only_visible: flag to return only information on visible surface elements
    @type only_visible: boolean
    @parameter plot_sort: flag to sort the surface elements from back to front
    @type plot_sort: boolean
    """
    myshape = star['gravx'].shape
    gravx,gravy,gravz = np.array([star['gravx'].ravel(),star['gravy'].ravel(),star['gravz'].ravel()])
    areas = star['areas'].ravel()
    teff = star['teff'].ravel()
    vx,vy,vz = star['vx'].ravel(),star['vy'].ravel(),star['vz'].ravel()
    #-- if 'x' is not in the star's record array, we assume the polar coordinates
    #   are in there and convert them to Cartesian coordinates
    if not 'x' in star.dtype.names:
        x,y,z = vectors.spher2cart_coord(star['r'].ravel(),star['phi'].ravel(),star['theta'].ravel())
    else:
        x,y,z = star['x'].ravel(),star['y'].ravel(),star['z'].ravel(),
    
    #-- first we rotate in the XY plane (only for surface coordinates is the
    #   coordinate zeropoint important, the rest are vectors!):
    x,y = vectors.rotate(x,y,view_long[0],x0=view_long[1],y0=view_long[2])
    gravx,gravy = vectors.rotate(gravx,gravy,view_long[0])
    vx,vy = vectors.rotate(vx,vy,view_long[0])
    #-- then we rotate in the YZ plane:
    if view_lat[0]!=pi/2:
        rot_i = -(pi/2 - view_lat[0])
        x,z = vectors.rotate(x,z,rot_i)
        gravx,gravz = vectors.rotate(gravx,gravz,rot_i)
        vx,vz = vectors.rotate(vx,vz,rot_i)
    #-- ... and project the fluxes in the line of sight, which is now in the XY
    #   direction:
    view_vector = np.array([1.,0,0])#np.array([-sin(pi/2),0,-cos(pi/2)])
    grav_local = np.array([gravx,gravy,gravz])
    proj_flux,mus = projected_intensity(teff,grav_local,areas,view_vector,photband=photband)
    
    #-- we now construct a copy of the star record array with the changed
    #   coordinates
    new_star = star.copy()
    new_star['gravx'],new_star['gravy'],new_star['gravz'] = gravx,gravy,gravz
    new_star['vx'],new_star['vy'],new_star['vz'] = vx,vy,vz
    if 'x' in star.dtype.names:
        new_star['x'],new_star['y'],new_star['z'] = x*scale_factor,y*scale_factor,z*scale_factor
    else:
        new_star = pl.mlab.rec_append_fields(new_star,'x',x*scale_factor)
        new_star = pl.mlab.rec_append_fields(new_star,'y',y*scale_factor)
        new_star = pl.mlab.rec_append_fields(new_star,'z',z*scale_factor)
    new_star = pl.mlab.rec_append_fields(new_star,'projflux',proj_flux)
    new_star = pl.mlab.rec_append_fields(new_star,'eyeflux',proj_flux/areas)
    new_star = pl.mlab.rec_append_fields(new_star,'mu',mus)
    
    #-- clip visible areas and sort in plotting order if necessary
    if only_visible:
        new_star = new_star[-np.isnan(new_star['projflux'])]
    if plot_sort:
        new_star = new_star[np.argsort(new_star['x'])]
    return new_star
Exemplo n.º 9
0
 
 theta,phi must be generated like mgrid(theta_range,phi_range)
 
 usually, the surfnormals are acquired via differentiation of a gravity potential,
 and is then equal to the *negative* of the local surface gravity.
 """
 theta,phi = mygrid[:2]
 if gtype=='spher':
     #-- compute the grid size at each location
     dtheta = theta[1:]-theta[:-1]
     dtheta = np.vstack([dtheta,dtheta[-1]])
     
     dphi = phi[:,1:]-phi[:,:-1]
     dphi = np.column_stack([dphi,dphi[:,-1]])
     #-- compute the angle between the surface normal and the radius vector
     x,y,z = vectors.spher2cart_coord(r,phi,theta)
     
     a = np.array([x,y,z])
     b = np.array([surfnormal_x,surfnormal_y,surfnormal_z])
     
     cos_gamma = vectors.cos_angle(a,b)
     
     return r**2 * sin(theta) * dtheta * dphi / cos_gamma, cos_gamma
 
 elif gtype=='delaunay':
     #-- compute the angle between the surface normal and the radius vector
     x,y,z = vectors.spher2cart_coord(r,phi,theta)
     a = np.array([x,y,z])
     b = np.array([surfnormal_x,surfnormal_y,surfnormal_z])        
     cos_gamma = vectors.cos_angle(a,b)