FlexiBrain / flexibrain /models /layers /pos_embed.py
OneMore1's picture
Sync from GitHub FlexiBrain main
6a51385 verified
Raw
History Blame Contribute Delete
2.24 kB
import math
from typing import Tuple
import torch
import torch.nn as nn
def stape_patch_world_coords_physical(
X:int, Y:int, Z:int,
kx:int, ky:int, kz:int,
affine: torch.Tensor,
rho_mm: Tuple[float, float, float],
device=None, dtype=None
):
if device is None: device = affine.device
if dtype is None: dtype = torch.float32
A = affine[:3, :3].to(device=device, dtype=dtype) # [3,3]
t = affine[:3, 3].to(device=device, dtype=dtype) # [3]
Lx, Ly, Lz = X//kx, Y//ky, Z//kz
icx = torch.arange(Lx, device=device, dtype=dtype)*kx + (kx-1)*0.5
icy = torch.arange(Ly, device=device, dtype=dtype)*ky + (ky-1)*0.5
icz = torch.arange(Lz, device=device, dtype=dtype)*kz + (kz-1)*0.5
gx, gy, gz = torch.meshgrid(icx, icy, icz, indexing='ij') # [Lx,Ly,Lz]
idx = torch.stack([gx, gy, gz], dim=-1).reshape(-1, 3) # [N,3]
coords = idx @ A.T + t # [N,3]
return coords
class FixedSinCos3DPE(nn.Module):
def __init__(self, embed_dim:int, num_freq:int=12,
space_scale:float=1.0, learnable_proj: bool=True):
super().__init__()
self.embed_dim = embed_dim
self.num_freq = num_freq
freq = torch.exp(torch.linspace(0, math.log(10000.0), num_freq)) / 10000.0
self.register_buffer('freq', freq) # [num_freq]
self.space_scale = space_scale
in_dim = 3 * 2 * num_freq
self.proj = nn.Linear(in_dim, embed_dim, bias=False) if learnable_proj else nn.Identity()
def forward(self, xyz: torch.Tensor):
"""
xyz: [B, L, 3]
return: [B, L, embed_dim]
"""
B, L, _ = xyz.shape
x = xyz[..., 0] * self.space_scale
y = xyz[..., 1] * self.space_scale
z = xyz[..., 2] * self.space_scale
freq = self.freq.to(device=xyz.device, dtype=xyz.dtype)
def enc(u):
u = u[..., None] * freq # [B,L,num_freq]
return torch.cat([torch.sin(u), torch.cos(u)], dim=-1) # [B,L,2*num_freq]
feats = torch.cat([enc(x), enc(y), enc(z)], dim=-1) # [B,L, 3*2*num_freq]
return self.proj(feats) # [B,L,C]