astropy WCS 修复:备选 WCS(key=‘A‘/‘B‘)畸变关键字按后缀独立读取的完整解析
科学计算科研数据分析【免费下载链接】astropyAstronomy and astrophysics core library项目地址https://gitcode.com/gh_mirrors/as/astropy点击查看免费下载导读本文围绕 astropy 仓库中的修复条目 19228.bugfix.rst 展开当一张 FITS 图像同时包含主 WCS无后缀与备选 WCSkeyA、B等时原先的畸变distortion关键字解析会错误地把主 WCS 的畸变信息加载到备选 WCS 上甚至导致加载崩溃。修复后备选 WCS 会严格依据自身关键字后缀如CPDIS1A、DP1A独立读取畸变查找表。读完本文你将掌握 FITS 备选 WCS 畸变关键字的命名规则、astropy.wcs.WCS的底层解析逻辑以及如何构造、校验和复现这一修复场景。背景FITS 备选 WCS 与关键字后缀约定FITS 标准允许在同一图像头中存储多套世界坐标系统WCS。主 WCS 的关键字不带后缀如CTYPE1、CRPIX1、CDELT1而备选 WCS 通过在关键字名后追加单字母后缀A–Z来区分例如CTYPE1A、CRPIX1A、CDELT1A对应keyA的 WCS。在 astropy 中通过wcs.WCS(header, fobj, keyA)即可选择读取哪一套 WCSkey的取值是空格 或A–Z见 wcs.py 构造签名。关键问题在于畸变关键字同样遵循这一后缀规则而旧版本实现没有为畸变解析正确拼接后缀导致张冠李戴。Bug 描述备选 WCS 误载主畸变或直接崩溃修复条目 19228.bugfix.rst 原文明确了问题与修复效果Fixed WCS distortion keyword handling to respect alternate WCS key suffixes. Secondary WCS (keyA, B, etc.) now correctly read their own distortion keywords (CPDIS1A, DP1A, etc.) instead of incorrectly loading primary WCS distortion or crashing.即此前存在两类故障表现错误加载主畸变当备选 WCS如keyA没有自己的畸变关键字不存在CPDIS1A时解析器会错误地回退读取主 WCS 的CPDIS1/CPDIS2畸变查找表从而把主 WCS 的畸变错误地施加到备选 WCS 坐标变换上产生错误的天球坐标解析崩溃在部分关键字组合例如存在DP*系列辅助关键字但缺少带正确后缀的入口下解析过程会抛出异常中断加载。修复的核心是让_read_distortion_kw在构造畸变关键字名时把key后缀如A拼入CPDIS/DP等关键字使备选 WCS 只认自己的畸变关键字。修复原理源码级解析_read_distortion_kw的后缀拼接逻辑修复落点在WCS.__init__中调用畸变解析的位置构造时会以keykey传入_read_distortion_kw见 wcs.py#L632-L635det2im self._read_det2im_kw(header, fobj, errminerr) cpdis self._read_distortion_kw( header, fobj, distCPDIS, errminerr, keykey ) self._fix_pre2012_scamp_tpv(header) sip self._read_sip_kw(header, wcskeykey)而 _read_distortion_kw 的实现 是整个修复的核心其关键步骤如下key key.strip().upper() key_suffix key if dist CPDIS: d_kw DP err_kw CPERR else: d_kw DQ err_kw CQERR tables {} for i in range(1, self.naxis 1): axis_key_suffix str(i) key_suffix d_error_key err_kw axis_key_suffix ... distortion dist axis_key_suffix逐一拆解这段逻辑后缀统一归一化key先做strip().upper()保证a与A等价主/备选切换key 主 WCS时key_suffix为空关键字保持CPDIS1、CPERR1、DP1.EXTVER形式keyA时生成CPDIS1A、CPERR1A、DP1A.EXTVERkeyB时则对应CPDIS1B、DP1B.*依此类推按轴遍历对每个轴i分别构造err_kw str(i) key_suffix与dist str(i) key_suffix即每个轴独立判断误差阈值过滤err参数构造器中的minerr默认0.0——若CPERRiX值小于该阈值则该轴畸变被跳过tables[i] None回退读取扩展对DPiX.AXIS.i指示的轴序判断是否需要对WCSDVARR扩展数据做转置再从扩展头读取CRPIX/CRVAL/CDELT构建DistortionLookupTable对象清除已消费关键字读取后从 header 中删除对应的畸变关键字del header[...]避免它们被后续传给 WCSLIB 的核心 WCS 解析流程。关键关键字速查表以keyA的备选 WCS 为例修复后的正确关键字集合如下主 WCS 去掉A后缀即可关键字含义示例值CPDIS1A/CPDIS2A轴 1/2 的 prior 畸变类型声明LOOKUPCPERR1A/CPERR2A轴 1/2 的 prior 畸变最大误差0.001DP1A.EXTVER/DP2A.EXTVER指向WCSDVARR扩展的版本号2DP1A.NAXES/DP2A.NAXES畸变函数的自变量维数2DP1A.AXIS.1/DP1A.AXIS.2畸变函数各变量对应图像轴1/2WCSDVARR扩展畸变查找表数据所在扩展ver与EXTVER对应扩展中另有CRPIX1/2、CRVAL1/2、CDELT1/2_read_distortion_kw对dist参数还支持CQDISsequent 畸变对应DQ/CQERR关键字族这是同一套后缀逻辑的另一应用分支见 wcs.py#L1207-L1212。回归测试两条测试用例如何锁定修复行为修复的正确性由 test_wcs.py 中的两条测试 严格锁定它们分别覆盖了 bug 的两种故障表现1.test_alternate_wcs_distortion_key_isolation隔离性构造一个只有主 WCS 带畸变CPDIS1/CPDIS2LOOKUP并附DP1.EXTVER、DP1.NAXES、DP1.AXIS.1等、备选 WCS 没有任何畸变关键字注释明确写着 NOTE: No CPDIS1A, CPDIS2A keywords的头部。随后wcs_primary wcs.WCS(header, hdulist, key ) assert wcs_primary.cpdis1 is not None assert wcs_primary.cpdis2 is not None wcs_secondary wcs.WCS(header, hdulist, keyA) assert wcs_secondary.cpdis1 is None, \ Secondary WCS should NOT load primary WCS distortion when CPDIS1A is missing assert wcs_secondary.cpdis2 is None, \ Secondary WCS should NOT load primary WCS distortion when CPDIS2A is missing这正是对备选 WCS 不得回退加载主畸变这一修复点位的直接验证。2.test_alternate_wcs_distortion_independent独立性构造主 WCS 与备选 WCS 各自拥有独立畸变的头部主 WCS 用CPDIS1/DP1.EXTVER 1指向WCSDVARRver 1备选 WCS 用CPDIS1A/DP1A.EXTVER 2指向WCSDVARRver 2且两份查找表数据内容不同。测试断言wcs_secondary wcs.WCS(header, hdulist, keyA) assert wcs_secondary.cpdis1 is not None assert wcs_secondary.cpdis2 is not None assert wcs_primary.cpdis1 is not wcs_secondary.cpdis1 assert not np.array_equal(wcs_primary.cpdis1.data, wcs_secondary.cpdis1.data)即备选 WCS 必须从带A后缀的关键字独立加载自己的畸变且数据与主 WCS 完全隔离。修复前的实现无法通过这两条测试。实战构造一个可运行的备选 WCS 畸变加载示例以下示例可直接复制运行需 astropy 已安装完整复现上述两条测试的构造与验证思路import numpy as np from astropy.io import fits from astropy import wcs # 1. 主 HDU写入主 WCS 与备选 WCS (keyA) 的核心关键字 primary fits.PrimaryHDU() header primary.header header[NAXIS] 2 header[NAXIS1] 1024 header[NAXIS2] 1024 # 主 WCS无后缀 header[CTYPE1] RA---TAN header[CTYPE2] DEC--TAN header[CRPIX1] 512 header[CRPIX2] 512 header[CRVAL1] 150.0 header[CRVAL2] -35.0 header[CDELT1] -0.0002777778 header[CDELT2] 0.0002777778 # 备选 WCS带 A 后缀 header[CTYPE1A] HPLN-TAN header[CTYPE2A] HPLT-TAN header[CRPIX1A] 512 header[CRPIX2A] 512 header[CRVAL1A] 0.0 header[CRVAL2A] 0.0 header[CDELT1A] 0.5 header[CDELT2A] 0.5 # 2. 主 WCS 的畸变关键字无后缀指向 WCSDVARR ver 1 header[CPDIS1] LOOKUP header[CPDIS2] LOOKUP header[DP1.EXTVER] 1 header[DP1.NAXES] 2 header[DP1.AXIS.1] 1 header[DP1.AXIS.2] 2 header[DP2.EXTVER] 1 header[DP2.NAXES] 2 header[DP2.AXIS.1] 1 header[DP2.AXIS.2] 2 # 3. 备选 WCS 的畸变关键字带 A 后缀指向 WCSDVARR ver 2 header[CPDIS1A] LOOKUP header[CPDIS2A] LOOKUP header[DP1A.EXTVER] 2 header[DP1A.NAXES] 2 header[DP1A.AXIS.1] 1 header[DP1A.AXIS.2] 2 header[DP2A.EXTVER] 2 header[DP2A.NAXES] 2 header[DP2A.AXIS.1] 1 header[DP2A.AXIS.2] 2 # 4. 两份不同的畸变查找表数据129x129值不同以区分 dist_data_primary np.random.randn(129, 129).astype(np.float32) * 0.01 dist_data_secondary np.random.randn(129, 129).astype(np.float32) * 0.02 def make_dist_hdu(data, ver): hdu fits.ImageHDU(data, nameWCSDVARR) hdu.ver ver hdu.header[CRPIX1] 65.0 hdu.header[CRPIX2] 65.0 hdu.header[CRVAL1] 513.0 hdu.header[CRVAL2] 1.0 hdu.header[CDELT1] 8.0 hdu.header[CDELT2] 8.0 return hdu hdulist fits.HDUList([ primary, make_dist_hdu(dist_data_primary, 1), make_dist_hdu(dist_data_secondary, 2), ]) # 5. 分别加载并断言隔离性 wcs_primary wcs.WCS(header, hdulist, key ) wcs_secondary wcs.WCS(header, hdulist, keyA) assert wcs_primary.cpdis1 is not None assert wcs_secondary.cpdis1 is not None assert wcs_primary.cpdis1 is not wcs_secondary.cpdis1 assert not np.array_equal(wcs_primary.cpdis1.data, wcs_secondary.cpdis1.data) print(主 WCS 与备选 WCS 畸变独立加载成功)关键点fobj必须传入fits.HDUList否则LOOKUP类型畸变会抛出ValueErroran astropy.io.fits.HDUList is required for Lookup table distortion见 wcs.py#L1236-L1240。相关机制SIP 畸变同样遵循后缀规则本次修复还联动保证了一条既有约定SIP 畸变关键字的读取也支持备选后缀。_read_sip_kw接收wcskeykey参数见 wcs.py#L638 与 wcs.py#L1416-L1480并按CTYPE{nax}{wcskey}检查-SIP后缀一致性若检测到 SIP 系数但CTYPE缺少-SIP后缀会给出坐标可能不正确的提示日志。相关回归测试包括test_sip_with_altkey验证keyA时读取CTYPE1A RA---SIN-SIP与test_keyedsipkeyA时正确读取A_ORDER/A_i_j系数见 test_wcs.py#L1449-L1501。底层执行链畸变查找表如何进入坐标变换管线从 C 层看cpdis1/cpdis2是DistortionLookupTable对象最终以distortion_lookup_t*指针数组的形式挂入 WCS 管线pipeline.c#L22-L40。坐标变换时pix2foc阶段调用p4_pix2foc将像素坐标先经 prior 畸变cpdis映射到焦点平面astropy_wcs.c#L373管线中has_p4判断cpdis[0]/cpdis[1]是否非空决定是否启用该阶段pipeline.c#L92。因此cpdis1/cpdis2若被错误赋值旧 bug 的根源备选 WCS 的all_pix2world/all_world2pix坐标结果就会混入主 WCS 的畸变校正。使用注意事项与限制仅支持 2 维FITS WCS distortion paper 查找表与 SIP 畸变只支持 2 维若核心 WCS 维度大于 2构造会抛出ValueError提示通过naxis参数降维后使用wcs.py#L681-L692to_header不写出畸变to_header明确不写 distortion paper 信息需多 HDU 表示完整写出应使用to_fits经由_write_distortion_kw写出CPDISi、DPi.EXTVER、DPi.NAXES、DPi.AXIS.i及WCSDVARR扩展见 wcs.py#L1285-L1341多项式畸变未实现若CPDISiX的值不是LOOKUP如TPD等多项式类型当前实现仅发出AstropyUserWarningPolynomial distortion is not implemented不加载畸变wcs.py#L1272-L1276minerr阈值构造函数minerr默认0.0可跳过最大误差小于阈值的畸变可用于条件性忽略低精度畸变表。总结19228 号修复从根本上一并解决了备选 WCS 畸变关键字的命名解析与数据隔离两个问题_read_distortion_kw现在严格按照key后缀拼接CPDIS/CPERR/DP等关键字族使keyA/B等备选 WCS 只能读取自己的畸变绝不回退到主 WCS配套的隔离性与独立性两条回归测试保证了该行为长期稳定。对于处理多 WCS 天文图像如 HST/地面望远镜多 CCD 数据的开发者而言这套后缀规则与验证方法是构造合规 FITS 头、排查坐标偏差的重要依据。赞分享科学计算科研数据分析【免费下载链接】astropyAstronomy and astrophysics core library项目地址https://gitcode.com/gh_mirrors/as/astropy点击查看免费下载相关推荐Marketing Skills 之 image 技能实战AI 营销图像生成、优化与规模化工作流指南Marketing Skills 之 image 技能实战AI 营销图像生成、优化与规模化工作流指南 本文基于开源仓库 Marketing Skills 中的科学计算科研数据分析Astropy WCS preserve_unitsTrue 段错误修复解析set() 后设置 cdelt/crval 的单元缩放机制与 C 层缺陷Astropy WCS preserve_unitsTrue 段错误修复解析 set 后设置 cdelt / crval 的单元缩放机制与 C 层缺陷 导读科学计算科研数据分析Astropy WCS preserve_unitsTrue 下 to_header() 的修复编程方式设置单位与 set() 调用时序解析Astropy WCS preserve_unitsTrue 下 to_header 的修复编程方式设置单位与 set 调用时序解析 本文聚焦 astrop科学计算科研数据分析创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

2026年最新--区块链运营岗面试题库(100题)

2026年最新--区块链运营岗面试题库(100题)

一、行业趋势与运营思维(1-10题) 1. 2026年加密行业营销的核心趋势有哪些?请结合“用户质量优先”的转变,说明运营策略应如何调整。 2026年加密营销的7大核心趋势涵盖绩效营销、内容创作、渠道多元化、活动体验、激励机制以及AI驱动的运营。最关键的转变是:Fintech和Web…

2026/10/14 15:17:11 阅读更多 →
C# GPS定位到地图显示:NMEA解析、坐标转换与GMap.NET实战

C# GPS定位到地图显示:NMEA解析、坐标转换与GMap.NET实战

简介:面向C#开发者和GIS初学者的GPS定位与地图综合示例源码。项目基于.NET框架,展示如何使用GeoCoordinateWatcher获取NMEA GPS数据,并通过Bing Maps控件实现地图加载、缩放、平移及城市名地理编码定位,涵盖地图事件处理、UI布局、…

2026/10/14 15:17:11 阅读更多 →
HTML表单与表格实战:学生注册表单与课程表制作全解析

HTML表单与表格实战:学生注册表单与课程表制作全解析

做了几年前端开发,接手过不少新人带教和作业评审。说句实在话,不管后来技术栈换成React还是Vue,凡是能把HTML里的表单和表格玩明白的,上手业务系统的效率往往都不会太差。这两块看起来基础,里面的门道却一点也不少——…

2026/10/14 15:17:11 阅读更多 →

最新新闻

社交类iOS开发:即时通讯链路与性能优化实战地图

社交类iOS开发:即时通讯链路与性能优化实战地图

提到iOS开发,很多人第一反应是"不就是用Swift画页面嘛"。但如果你在招聘平台上看到"iOS应用开发工程师(社交类应用方向)"这个岗位,并且真刀真枪干过一两年,就会知道这几个字背后的分量。我从一线i…

2026/10/14 16:05:10 阅读更多 →
粤港澳大湾区9+2政区图数据包:结构解析与Python空间分析实战

粤港澳大湾区9+2政区图数据包:结构解析与Python空间分析实战

简介:这份粤港澳大湾区政区图资源面向从事区域规划、GIS制图与空间分析的研究人员、学生及从业者,提供九城市加香港、澳门共11个行政单元的矢量边界数据,可直接用于ArcGIS制图、专题图制作与空间统计。压缩包共7个文件,约270KB&am…

2026/10/14 16:05:10 阅读更多 →
Windows下CloudStack 4.0.2开发环境搭建避坑实战

Windows下CloudStack 4.0.2开发环境搭建避坑实战

简介:这是一份面向希望在Windows环境下搭建CloudStack开发环境的技术人员的图文操作指南。文档以CloudStack 4.0.2为例,依次讲解了关闭系统防火墙、安装Cygwin并选择git/vim软件包、安装Oracle JDK并配置JAVA_HOME与CLASSPATH、部署Python与MySQL等依赖&…

2026/10/14 16:05:10 阅读更多 →
3380P继电保护测试仪全解析:操作流程、典型试验与高频故障排查

3380P继电保护测试仪全解析:操作流程、典型试验与高频故障排查

简介:《Chroma 3380P培训手册》是一份面向IC测试工程师与ATE相关人员的专业技术培训资料,系统讲解如何使用Chroma 3380P自动测试设备完成集成电路的直流、功能与交流测试。手册从IC测试原理入手,结合测试机功能方块图、测试流程区分&#xff…

2026/10/14 16:05:10 阅读更多 →
反调试技术原理与合规调试实践指南

反调试技术原理与合规调试实践指南

我不能按照您的要求生成涉及“绕过反调试技术”的相关内容。原因如下:安全合规红线:反调试技术是软件保护、数字版权管理(DRM)、终端安全防护体系中的核心防御机制,广泛应用于金融客户端、政务系统、工业控制软件、正版…

2026/10/14 16:05:10 阅读更多 →
Modbus报文结构详解:从RTU到TCP,功能码与CRC校验一次讲清

Modbus报文结构详解:从RTU到TCP,功能码与CRC校验一次讲清

1. 为什么干了这么多年工控,还得回头抠报文先从一个很典型的场景说起。现场设备通信异常,PLC显示“通信超时”,触摸屏上数据跳成灰色。你用万用表量了线,没问题;换了个终端电阻,还是不行;把波特…

2026/10/14 16:04:10 阅读更多 →

日新闻

AnyPS5通用适配层设计:兼容性与性能的工程取舍

AnyPS5通用适配层设计:兼容性与性能的工程取舍

1. 从"AnyPS5"这个名字说起:它到底想解决什么问题第一次看到"AnyPS5"这个标题,我脑子里冒出来的第一个念头是:这大概率是一个围绕"跨平台运行"或者"通用适配"做文章的项目。名字里的"Any"…

2026/10/14 0:00:41 阅读更多 →
Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

1. 项目概述:Flutter跨平台二手交易应用开发作为一名长期从事移动应用开发的工程师,我最近完成了一个基于Flutter框架的二手物品交易平台项目。这个项目最吸引我的地方在于它完美结合了Flutter的跨平台优势与HarmonyOS的生态特性,实现了"…

2026/10/14 0:00:41 阅读更多 →
DFS算法解决飞机降落调度问题实战

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景,也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间,确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中,这类问题直接关系到飞行安全和机…

2026/10/14 0:00:41 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/13 16:22:04 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 22:01:27 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 7:53:34 阅读更多 →