Astropy自定义波长单位启用SI前缀(千λ、兆λ等)失效问题咨询
问题根因
你遇到的SI前缀不生效问题有两个核心原因:
- 自定义单位
lambdas仅在类实例化时临时创建,没有注册到astropy的全局单位注册表,astropy解析带前缀的单位字符串时无法识别该单位的前缀变体 - 每次实例化时重复生成单位实例,没有复用同一个单位定义,
prefixes=True的配置无法被全局解析逻辑感知
修复方案
- 第一步:将
lambdas单位的定义移到类外部,全局仅初始化一次,并注册到astropy的启用单位列表 - 第二步:修正单位格式配置的键名,将
format={'format': r'\lambda'}改为format={'latex': r'\lambda'},符合astropy的格式规范 - 第三步:删除类中重复的类定义代码,避免逻辑覆盖
- 第四步:类内部直接引用全局定义好的
lambdas单位,不再每次实例化时重复创建
如果需要支持单数形式lambda/klambda的单位名,可在def_unit中添加别名配置。
修正后完整代码
import astropy.units as un import astropy.constants as co import sys # 全局定义并注册自定义单位,添加别名支持单数lambda写法 lambdas = un.def_unit( ['lambdas', 'lambda'], format={'latex': r'\lambda'}, prefixes=True ) # 注册到astropy全局单位库,支持前缀解析 un.add_enabled_units([lambdas]) class uWavelength(un.Quantity): def __new__(cls, value, freq=None, dtype=None, copy=True, **kwargs): # 直接引用全局定义的lambdas单位 self = super().__new__(cls, value=value, unit=lambdas, dtype=dtype, copy=copy, **kwargs) self.freq = freq if self.freq is not None: self.equivalencies = self.lambdas_equivalencies() return self @property def freq(self): return self._freq @freq.setter def freq(self, val): if val is not None: self._equivalencies = self.lambdas_equivalencies(restfreq=val) self._freq = val @property def equivalencies(self): return self._equivalencies @equivalencies.setter def equivalencies(self, val): self._equivalencies = val def lambdas_equivalencies(self, restfreq=None): if self.freq is not None: restfreq_hz = self.freq.to(un.Hz, equivalencies=un.spectral()) elif restfreq is not None: restfreq_hz = restfreq.to(un.Hz, equivalencies=un.spectral()) else: sys.exit("Frequency not provided") eq = [ (self.unit, un.s, lambda x: x / restfreq_hz, lambda x: x * restfreq_hz), (self.unit, un.m, lambda x: x / restfreq_hz * co.c.to(un.m / un.s).value, lambda x: x / co.c.to(un.m / un.s).value * restfreq_hz), (un.m, un.s, lambda x: x / co.c.to(un.m / un.s).value, lambda x: x * co.c.to(un.m / un.s).value), ] return eq def to(self, unit, restfreq=None, copy=True): equiv = [] if restfreq is None: equiv = self.equivalencies else: equiv = self.lambdas_equivalencies(restfreq=restfreq) unit = un.Unit(unit) if copy: value = self._to_value(unit, equiv) else: value = self.to_value(unit, equiv) return self._new_view(value, unit)
验证示例
# 测试示例 freq = 1.4 * un.GHz # 定义2 lambda的量 wl = uWavelength(2, freq=freq) # 转千lambda,输出0.002 klambda print(wl.to('klambda')) # 从千lambda初始化 wl2 = uWavelength(0.005, freq=freq) # 转米,输出约1.071 m print(wl2.to('m'))
内容的提问来源于stack exchange,提问作者Miguel Cárcamo
相关产品推荐
相关产品推荐

