# XP.Scan 扫描配置文件设计文档 ## 1. 需求概述 在平面CT扫描采集过程中,需要将当前扫描的所有参数信息(项目信息、射线源参数、探测器参数、运动控制参数、扫描配置、校正配置)打包为一个配置对象,最终序列化为 INI 格式文件传递给重构电脑。 INI 文件结构与立式CT采集配置兼容,包含 6 个 Section: - `[Project_Information]` — 项目基本信息 - `[XRay]` — 射线源参数 - `[Detector]` — 探测器参数 - `[Move_Control]` — 运动控制轴位置 - `[Scan_Config]` — 扫描配置 - `[Correction_Config]` — 校正参数 ## 2. 设计方案对比 | 方案 | 优点 | 缺点 | 推荐 | |------|------|------|------| | A. 单个大类 `ScanConfig` | 简单直接 | 字段太多,职责不清 | ✗ | | B. 分组模型 + 序列化服务 | 职责清晰,可测试,可扩展 | 类稍多 | ✓ | | C. Dictionary + 手写序列化 | 灵活 | 无类型安全,易出错 | ✗ | **选择方案 B**:用分组模型类映射 INI 的每个 Section,加一个序列化服务负责读写 INI 文件。 ## 3. 数据模型设计 ### 3.1 整体结构 ``` ScanConfigData (顶层聚合) ├── ProjectInfo → [Project_Information] ├── XRayConfig → [XRay] ├── DetectorConfig → [Detector] ├── MoveControlConfig → [Move_Control] ├── ScanSettings → [Scan_Config] └── CorrectionConfig → [Correction_Config] ``` ### 3.2 类定义 ```csharp namespace XP.Scan.Models { /// /// 扫描配置数据(顶层聚合,对应完整 INI 文件) /// public class ScanConfigData { public ProjectInfo ProjectInfo { get; set; } = new(); public XRayConfig XRay { get; set; } = new(); public DetectorConfig Detector { get; set; } = new(); public MoveControlConfig MoveControl { get; set; } = new(); public ScanSettings ScanSettings { get; set; } = new(); public CorrectionConfig Correction { get; set; } = new(); } } ``` #### [Project_Information] ```csharp public class ProjectInfo { /// 图像保存路径 public string FileSave { get; set; } = string.Empty; /// 滤波片1 public string Filter1 { get; set; } = "None"; /// 滤波片2 public string Filter2 { get; set; } = "None"; /// 项目名称 public string Project { get; set; } = string.Empty; /// 样品编号 public string SampleNo { get; set; } = string.Empty; /// 扫描模式名称 public string ScanMode { get; set; } = "QuickScan"; } ``` #### [XRay] ```csharp public class XRayConfig { /// 管电流 (μA) public int Current_uA { get; set; } /// 焦点尺寸 public string Focus { get; set; } = string.Empty; /// 管电压 (kV) public int Voltage_kV { get; set; } } ``` #### [Detector] ```csharp public class DetectorConfig { /// 帧合并数 public int Det_Avg_Frames { get; set; } = 1; /// Binning 模式 public string Det_Binning { get; set; } = "1*1"; /// 帧率 public int Det_Frame_rate { get; set; } = 2; /// 增益 (PGA) public int Det_PGA { get; set; } = 6; // ROI 参数 public int Image_ROI_Height { get; set; } public int Image_ROI_Width { get; set; } public int Image_ROI_xStart { get; set; } public int Image_ROI_xEnd { get; set; } public int Image_ROI_yStart { get; set; } public int Image_ROI_yEnd { get; set; } public int Image_ROI_zStart { get; set; } public int Image_ROI_zEnd { get; set; } // 图像尺寸 public int Image_Size_Height { get; set; } public int Image_Size_Width { get; set; } // 物理尺寸 (mm) public double Physical_Size_X { get; set; } public double Physical_Size_Y { get; set; } // 像素尺寸 (mm) public double Pixel_X { get; set; } public double Pixel_Y { get; set; } } ``` #### [Move_Control] ```csharp public class MoveControlConfig { /// 探测器 X 位置 (mm) public double DetX { get; set; } /// 探测器 Y 位置 (mm) public double DetY { get; set; } /// 探测器 Z 位置 (mm) public double DetZ { get; set; } /// 旋转台角度 (°) public double Rotation { get; set; } /// 样品台 X 位置 (mm) — 即 SOD public double X { get; set; } /// 射线源 Z 位置 (mm) public double XRAYZ { get; set; } /// 样品台 Y 位置 (mm) public double Y { get; set; } } ``` #### [Scan_Config] ```csharp public class ScanSettings { /// 采集张数 public int AcquiresNums { get; set; } /// 旋转角度 (°) public double RotateDegree { get; set; } /// 扫描模式描述 public string ScanMode { get; set; } = string.Empty; /// SDD — 射线源到探测器距离 (mm) public double SDD { get; set; } /// SOD — 射线源到样品距离 (mm) public double SOD { get; set; } } ``` #### [Correction_Config] ```csharp public class CorrectionConfig { /// 探测器水平偏移 (mm) public double Detector_Horizontal_Offset { get; set; } /// 探测器旋转偏移 (°) public double Detector_Rotation_Offset { get; set; } } ``` ## 4. INI 序列化服务设计 ### 4.1 接口 ```csharp namespace XP.Scan.Services { public interface IScanConfigSerializer { /// 将配置数据序列化为 INI 格式字符串 string Serialize(ScanConfigData config); /// 将配置数据写入 INI 文件 void SaveToFile(ScanConfigData config, string filePath); /// 从 INI 文件读取配置数据 ScanConfigData LoadFromFile(string filePath); } } ``` ### 4.2 实现方案 不引入第三方 INI 库,手写轻量级序列化,原因: - INI 结构简单固定(6 个 Section,字段已知) - 避免额外 NuGet 依赖 - 完全可控,格式与立式CT兼容 核心思路:用 `[IniSection("Section_Name")]` 和 `[IniKey("Key_Name")]` 特性标注模型属性,序列化时通过反射自动生成 INI 内容。 ### 4.3 特性定义 ```csharp /// 标记 INI Section 名称 [AttributeUsage(AttributeTargets.Class)] public class IniSectionAttribute : Attribute { public string SectionName { get; } public IniSectionAttribute(string sectionName) => SectionName = sectionName; } /// 标记 INI Key 名称(可选,默认用属性名) [AttributeUsage(AttributeTargets.Property)] public class IniKeyAttribute : Attribute { public string KeyName { get; } public IniKeyAttribute(string keyName) => KeyName = keyName; } ``` ### 4.4 模型标注示例 ```csharp [IniSection("Project_Information")] public class ProjectInfo { [IniKey("fileSave")] public string FileSave { get; set; } = string.Empty; [IniKey("filter1")] public string Filter1 { get; set; } = "None"; // ... } [IniSection("XRay")] public class XRayConfig { [IniKey("Current_uA")] public int Current_uA { get; set; } // ... } ``` ### 4.5 序列化输出示例 ```ini [Project_Information] fileSave=D:\HexagonCTData\Test_2026-04-21\Image filter1=Cu 0.2mm filter2=None Project=Test SampleNo= ScanMode=QuickScan [XRay] Current_uA=1000 Focus=450um Voltage_kV=450 [Detector] Det_Avg_Frames=1 Det_Binning=1*1 ... ``` ## 5. 文件结构规划 ``` XP.Scan/ ├── Models/ │ ├── ScanConfigData.cs # 顶层聚合类 │ ├── ProjectInfo.cs # [Project_Information] │ ├── XRayConfig.cs # [XRay] │ ├── DetectorConfig.cs # [Detector] │ ├── MoveControlConfig.cs # [Move_Control] │ ├── ScanSettings.cs # [Scan_Config] │ └── CorrectionConfig.cs # [Correction_Config] │ ├── Attributes/ │ ├── IniSectionAttribute.cs # Section 特性 │ └── IniKeyAttribute.cs # Key 特性 │ ├── Services/ │ ├── IScanConfigSerializer.cs # 序列化接口 │ └── ScanConfigSerializer.cs # 序列化实现(反射 + 手写 INI) │ └── ... ``` ## 6. 使用流程 ``` 1. 扫描开始前,从各硬件服务收集参数 → 填充 ScanConfigData var config = new ScanConfigData(); config.XRay.Voltage_kV = raySourceService.CurrentVoltage; config.XRay.Current_uA = raySourceService.CurrentCurrent; config.Detector.Det_Avg_Frames = detectorService.AvgFrames; config.MoveControl.X = motionService.GetPosition(AxisId.StageX); config.ScanSettings.AcquiresNums = acquisitionCount; // ... 2. 序列化为 INI 文件 var serializer = new ScanConfigSerializer(); serializer.SaveToFile(config, @"D:\HexagonCTData\Test\ScanConfig.ini"); 3. 传递给重构电脑(文件拷贝或网络传输) ``` ## 7. 设计决策 | 决策 | 选择 | 理由 | |------|------|------| | 数据模型 | 分组类(每个 Section 一个类) | 职责清晰,属性有类型安全 | | 序列化方式 | 自定义特性 + 反射 | 轻量,无第三方依赖,格式完全可控 | | INI Key 映射 | `[IniKey]` 特性 | 属性名可以用 C# 命名规范,INI Key 保持与立式CT兼容 | | 数值格式 | `InvariantCulture` | 避免不同系统区域设置导致小数点格式不一致 | | 文件编码 | UTF-8 无 BOM | 兼容性最好 | ## 8. 扩展性 - 新增 Section:创建新模型类 + 标注 `[IniSection]` + 在 `ScanConfigData` 中添加属性 - 新增字段:在对应模型类中添加属性 + 标注 `[IniKey]` - 反序列化:`LoadFromFile` 支持从 INI 文件回读配置(用于加载历史扫描参数) - 验证:可在模型类中添加 `Validate()` 方法,检查参数范围合法性 --- **版本:** 1.0 **最后更新:** 2026-04-21