diff --git a/data/raw/A1 b/data/raw/A1 new file mode 100644 index 0000000..398cf81 Binary files /dev/null and b/data/raw/A1 differ diff --git a/data/raw/A10 b/data/raw/A10 new file mode 100644 index 0000000..83d95f5 Binary files /dev/null and b/data/raw/A10 differ diff --git a/data/raw/A100 b/data/raw/A100 new file mode 100644 index 0000000..95abbd4 Binary files /dev/null and b/data/raw/A100 differ diff --git a/data/raw/A101 b/data/raw/A101 new file mode 100644 index 0000000..b786641 Binary files /dev/null and b/data/raw/A101 differ diff --git a/data/raw/A102 b/data/raw/A102 new file mode 100644 index 0000000..4a3e575 Binary files /dev/null and b/data/raw/A102 differ diff --git a/data/raw/A103 b/data/raw/A103 new file mode 100644 index 0000000..9f4d9ed Binary files /dev/null and b/data/raw/A103 differ diff --git a/data/raw/A104 b/data/raw/A104 new file mode 100644 index 0000000..156c50a Binary files /dev/null and b/data/raw/A104 differ diff --git a/data/raw/A105 b/data/raw/A105 new file mode 100644 index 0000000..d3a4621 Binary files /dev/null and b/data/raw/A105 differ diff --git a/data/raw/A106 b/data/raw/A106 new file mode 100644 index 0000000..b861a1a Binary files /dev/null and b/data/raw/A106 differ diff --git a/data/raw/A107 b/data/raw/A107 new file mode 100644 index 0000000..5e6af71 Binary files /dev/null and b/data/raw/A107 differ diff --git a/data/raw/A108 b/data/raw/A108 new file mode 100644 index 0000000..b28d934 Binary files /dev/null and b/data/raw/A108 differ diff --git a/data/raw/A109 b/data/raw/A109 new file mode 100644 index 0000000..7d6f97b Binary files /dev/null and b/data/raw/A109 differ diff --git a/data/raw/A11 b/data/raw/A11 new file mode 100644 index 0000000..657b107 Binary files /dev/null and b/data/raw/A11 differ diff --git a/data/raw/A110 b/data/raw/A110 new file mode 100644 index 0000000..2fbe6d9 Binary files /dev/null and b/data/raw/A110 differ diff --git a/data/raw/A111 b/data/raw/A111 new file mode 100644 index 0000000..0554487 Binary files /dev/null and b/data/raw/A111 differ diff --git a/data/raw/A112 b/data/raw/A112 new file mode 100644 index 0000000..eb2d634 Binary files /dev/null and b/data/raw/A112 differ diff --git a/data/raw/A113 b/data/raw/A113 new file mode 100644 index 0000000..2d85255 Binary files /dev/null and b/data/raw/A113 differ diff --git a/data/raw/A114 b/data/raw/A114 new file mode 100644 index 0000000..a5dbb91 Binary files /dev/null and b/data/raw/A114 differ diff --git a/data/raw/A115 b/data/raw/A115 new file mode 100644 index 0000000..e40b1bc Binary files /dev/null and b/data/raw/A115 differ diff --git a/data/raw/A116 b/data/raw/A116 new file mode 100644 index 0000000..2052556 Binary files /dev/null and b/data/raw/A116 differ diff --git a/data/raw/A117 b/data/raw/A117 new file mode 100644 index 0000000..f28699e Binary files /dev/null and b/data/raw/A117 differ diff --git a/data/raw/A118 b/data/raw/A118 new file mode 100644 index 0000000..67cee86 Binary files /dev/null and b/data/raw/A118 differ diff --git a/data/raw/A119 b/data/raw/A119 new file mode 100644 index 0000000..9227533 Binary files /dev/null and b/data/raw/A119 differ diff --git a/data/raw/A12 b/data/raw/A12 new file mode 100644 index 0000000..57e31e8 Binary files /dev/null and b/data/raw/A12 differ diff --git a/data/raw/A120 b/data/raw/A120 new file mode 100644 index 0000000..0e630e6 Binary files /dev/null and b/data/raw/A120 differ diff --git a/data/raw/A121 b/data/raw/A121 new file mode 100644 index 0000000..24daea1 Binary files /dev/null and b/data/raw/A121 differ diff --git a/data/raw/A122 b/data/raw/A122 new file mode 100644 index 0000000..c012a54 Binary files /dev/null and b/data/raw/A122 differ diff --git a/data/raw/A123 b/data/raw/A123 new file mode 100644 index 0000000..d43aa81 Binary files /dev/null and b/data/raw/A123 differ diff --git a/data/raw/A124 b/data/raw/A124 new file mode 100644 index 0000000..eb31a1f Binary files /dev/null and b/data/raw/A124 differ diff --git a/data/raw/A125 b/data/raw/A125 new file mode 100644 index 0000000..e319cf0 Binary files /dev/null and b/data/raw/A125 differ diff --git a/data/raw/A126 b/data/raw/A126 new file mode 100644 index 0000000..247376d Binary files /dev/null and b/data/raw/A126 differ diff --git a/data/raw/A127 b/data/raw/A127 new file mode 100644 index 0000000..dfc9889 Binary files /dev/null and b/data/raw/A127 differ diff --git a/data/raw/A128 b/data/raw/A128 new file mode 100644 index 0000000..58526e6 Binary files /dev/null and b/data/raw/A128 differ diff --git a/data/raw/A129 b/data/raw/A129 new file mode 100644 index 0000000..a2d6db8 Binary files /dev/null and b/data/raw/A129 differ diff --git a/data/raw/A13 b/data/raw/A13 new file mode 100644 index 0000000..a9430ba Binary files /dev/null and b/data/raw/A13 differ diff --git a/data/raw/A130 b/data/raw/A130 new file mode 100644 index 0000000..145f1ce Binary files /dev/null and b/data/raw/A130 differ diff --git a/data/raw/A131 b/data/raw/A131 new file mode 100644 index 0000000..b45e3e7 Binary files /dev/null and b/data/raw/A131 differ diff --git a/data/raw/A132 b/data/raw/A132 new file mode 100644 index 0000000..b2a9285 Binary files /dev/null and b/data/raw/A132 differ diff --git a/data/raw/A133 b/data/raw/A133 new file mode 100644 index 0000000..0a19d4a Binary files /dev/null and b/data/raw/A133 differ diff --git a/data/raw/A134 b/data/raw/A134 new file mode 100644 index 0000000..2aa46f4 Binary files /dev/null and b/data/raw/A134 differ diff --git a/data/raw/A135 b/data/raw/A135 new file mode 100644 index 0000000..70fcc9c Binary files /dev/null and b/data/raw/A135 differ diff --git a/data/raw/A136 b/data/raw/A136 new file mode 100644 index 0000000..2d8d4f8 Binary files /dev/null and b/data/raw/A136 differ diff --git a/data/raw/A137 b/data/raw/A137 new file mode 100644 index 0000000..e41ccef Binary files /dev/null and b/data/raw/A137 differ diff --git a/data/raw/A138 b/data/raw/A138 new file mode 100644 index 0000000..fba11fd Binary files /dev/null and b/data/raw/A138 differ diff --git a/data/raw/A139 b/data/raw/A139 new file mode 100644 index 0000000..499dc61 Binary files /dev/null and b/data/raw/A139 differ diff --git a/data/raw/A14 b/data/raw/A14 new file mode 100644 index 0000000..2445a58 Binary files /dev/null and b/data/raw/A14 differ diff --git a/data/raw/A140 b/data/raw/A140 new file mode 100644 index 0000000..409dff4 Binary files /dev/null and b/data/raw/A140 differ diff --git a/data/raw/A141 b/data/raw/A141 new file mode 100644 index 0000000..14ba534 Binary files /dev/null and b/data/raw/A141 differ diff --git a/data/raw/A142 b/data/raw/A142 new file mode 100644 index 0000000..af39808 Binary files /dev/null and b/data/raw/A142 differ diff --git a/data/raw/A143 b/data/raw/A143 new file mode 100644 index 0000000..29c4646 Binary files /dev/null and b/data/raw/A143 differ diff --git a/data/raw/A144 b/data/raw/A144 new file mode 100644 index 0000000..057e78a Binary files /dev/null and b/data/raw/A144 differ diff --git a/data/raw/A145 b/data/raw/A145 new file mode 100644 index 0000000..34562b4 Binary files /dev/null and b/data/raw/A145 differ diff --git a/data/raw/A146 b/data/raw/A146 new file mode 100644 index 0000000..95c22b3 Binary files /dev/null and b/data/raw/A146 differ diff --git a/data/raw/A147 b/data/raw/A147 new file mode 100644 index 0000000..cf56963 Binary files /dev/null and b/data/raw/A147 differ diff --git a/data/raw/A148 b/data/raw/A148 new file mode 100644 index 0000000..0c74ce0 Binary files /dev/null and b/data/raw/A148 differ diff --git a/data/raw/A149 b/data/raw/A149 new file mode 100644 index 0000000..f4197d6 Binary files /dev/null and b/data/raw/A149 differ diff --git a/data/raw/A15 b/data/raw/A15 new file mode 100644 index 0000000..c0541cc Binary files /dev/null and b/data/raw/A15 differ diff --git a/data/raw/A150 b/data/raw/A150 new file mode 100644 index 0000000..5ed0d85 Binary files /dev/null and b/data/raw/A150 differ diff --git a/data/raw/A151 b/data/raw/A151 new file mode 100644 index 0000000..5c0c58c Binary files /dev/null and b/data/raw/A151 differ diff --git a/data/raw/A152 b/data/raw/A152 new file mode 100644 index 0000000..db772bd Binary files /dev/null and b/data/raw/A152 differ diff --git a/data/raw/A153 b/data/raw/A153 new file mode 100644 index 0000000..5f0642d Binary files /dev/null and b/data/raw/A153 differ diff --git a/data/raw/A154 b/data/raw/A154 new file mode 100644 index 0000000..5216ded Binary files /dev/null and b/data/raw/A154 differ diff --git a/data/raw/A155 b/data/raw/A155 new file mode 100644 index 0000000..56702fe Binary files /dev/null and b/data/raw/A155 differ diff --git a/data/raw/A156 b/data/raw/A156 new file mode 100644 index 0000000..2c4e967 Binary files /dev/null and b/data/raw/A156 differ diff --git a/data/raw/A157 b/data/raw/A157 new file mode 100644 index 0000000..443d61a Binary files /dev/null and b/data/raw/A157 differ diff --git a/data/raw/A158 b/data/raw/A158 new file mode 100644 index 0000000..36df899 Binary files /dev/null and b/data/raw/A158 differ diff --git a/data/raw/A159 b/data/raw/A159 new file mode 100644 index 0000000..c5c7c34 Binary files /dev/null and b/data/raw/A159 differ diff --git a/data/raw/A16 b/data/raw/A16 new file mode 100644 index 0000000..7417951 Binary files /dev/null and b/data/raw/A16 differ diff --git a/data/raw/A160 b/data/raw/A160 new file mode 100644 index 0000000..2412a5d Binary files /dev/null and b/data/raw/A160 differ diff --git a/data/raw/A161 b/data/raw/A161 new file mode 100644 index 0000000..0ce8d98 Binary files /dev/null and b/data/raw/A161 differ diff --git a/data/raw/A162 b/data/raw/A162 new file mode 100644 index 0000000..1f8983d Binary files /dev/null and b/data/raw/A162 differ diff --git a/data/raw/A163 b/data/raw/A163 new file mode 100644 index 0000000..95e8203 Binary files /dev/null and b/data/raw/A163 differ diff --git a/data/raw/A164 b/data/raw/A164 new file mode 100644 index 0000000..a32c439 Binary files /dev/null and b/data/raw/A164 differ diff --git a/data/raw/A165 b/data/raw/A165 new file mode 100644 index 0000000..76a590d Binary files /dev/null and b/data/raw/A165 differ diff --git a/data/raw/A166 b/data/raw/A166 new file mode 100644 index 0000000..3cb5309 Binary files /dev/null and b/data/raw/A166 differ diff --git a/data/raw/A167 b/data/raw/A167 new file mode 100644 index 0000000..c8503ca Binary files /dev/null and b/data/raw/A167 differ diff --git a/data/raw/A168 b/data/raw/A168 new file mode 100644 index 0000000..b70c315 Binary files /dev/null and b/data/raw/A168 differ diff --git a/data/raw/A169 b/data/raw/A169 new file mode 100644 index 0000000..00667dd Binary files /dev/null and b/data/raw/A169 differ diff --git a/data/raw/A17 b/data/raw/A17 new file mode 100644 index 0000000..b4c0eb0 Binary files /dev/null and b/data/raw/A17 differ diff --git a/data/raw/A170 b/data/raw/A170 new file mode 100644 index 0000000..fbc69eb Binary files /dev/null and b/data/raw/A170 differ diff --git a/data/raw/A171 b/data/raw/A171 new file mode 100644 index 0000000..10c8274 Binary files /dev/null and b/data/raw/A171 differ diff --git a/data/raw/A172 b/data/raw/A172 new file mode 100644 index 0000000..e911384 Binary files /dev/null and b/data/raw/A172 differ diff --git a/data/raw/A173 b/data/raw/A173 new file mode 100644 index 0000000..bb62f34 Binary files /dev/null and b/data/raw/A173 differ diff --git a/data/raw/A174 b/data/raw/A174 new file mode 100644 index 0000000..a7a8176 Binary files /dev/null and b/data/raw/A174 differ diff --git a/data/raw/A175 b/data/raw/A175 new file mode 100644 index 0000000..323e5da Binary files /dev/null and b/data/raw/A175 differ diff --git a/data/raw/A176 b/data/raw/A176 new file mode 100644 index 0000000..69c7919 Binary files /dev/null and b/data/raw/A176 differ diff --git a/data/raw/A177 b/data/raw/A177 new file mode 100644 index 0000000..a916242 Binary files /dev/null and b/data/raw/A177 differ diff --git a/data/raw/A178 b/data/raw/A178 new file mode 100644 index 0000000..4adbda7 Binary files /dev/null and b/data/raw/A178 differ diff --git a/data/raw/A179 b/data/raw/A179 new file mode 100644 index 0000000..1a70270 Binary files /dev/null and b/data/raw/A179 differ diff --git a/data/raw/A18 b/data/raw/A18 new file mode 100644 index 0000000..d11a69a Binary files /dev/null and b/data/raw/A18 differ diff --git a/data/raw/A180 b/data/raw/A180 new file mode 100644 index 0000000..fd6fcb6 Binary files /dev/null and b/data/raw/A180 differ diff --git a/data/raw/A181 b/data/raw/A181 new file mode 100644 index 0000000..e51bf90 Binary files /dev/null and b/data/raw/A181 differ diff --git a/data/raw/A182 b/data/raw/A182 new file mode 100644 index 0000000..da1bd9a Binary files /dev/null and b/data/raw/A182 differ diff --git a/data/raw/A183 b/data/raw/A183 new file mode 100644 index 0000000..dda5b44 Binary files /dev/null and b/data/raw/A183 differ diff --git a/data/raw/A184 b/data/raw/A184 new file mode 100644 index 0000000..2154906 Binary files /dev/null and b/data/raw/A184 differ diff --git a/data/raw/A185 b/data/raw/A185 new file mode 100644 index 0000000..2f6d568 Binary files /dev/null and b/data/raw/A185 differ diff --git a/data/raw/A186 b/data/raw/A186 new file mode 100644 index 0000000..accf59a Binary files /dev/null and b/data/raw/A186 differ diff --git a/data/raw/A187 b/data/raw/A187 new file mode 100644 index 0000000..06e5ad1 Binary files /dev/null and b/data/raw/A187 differ diff --git a/data/raw/A188 b/data/raw/A188 new file mode 100644 index 0000000..ff7f0b9 Binary files /dev/null and b/data/raw/A188 differ diff --git a/data/raw/A189 b/data/raw/A189 new file mode 100644 index 0000000..2d6875b Binary files /dev/null and b/data/raw/A189 differ diff --git a/data/raw/A19 b/data/raw/A19 new file mode 100644 index 0000000..4d6d514 Binary files /dev/null and b/data/raw/A19 differ diff --git a/data/raw/A190 b/data/raw/A190 new file mode 100644 index 0000000..80905a3 Binary files /dev/null and b/data/raw/A190 differ diff --git a/data/raw/A191 b/data/raw/A191 new file mode 100644 index 0000000..86af2cb Binary files /dev/null and b/data/raw/A191 differ diff --git a/data/raw/A192 b/data/raw/A192 new file mode 100644 index 0000000..db5e2b5 Binary files /dev/null and b/data/raw/A192 differ diff --git a/data/raw/A193 b/data/raw/A193 new file mode 100644 index 0000000..bf1ebb2 Binary files /dev/null and b/data/raw/A193 differ diff --git a/data/raw/A194 b/data/raw/A194 new file mode 100644 index 0000000..3d0fa90 Binary files /dev/null and b/data/raw/A194 differ diff --git a/data/raw/A195 b/data/raw/A195 new file mode 100644 index 0000000..d4496f0 Binary files /dev/null and b/data/raw/A195 differ diff --git a/data/raw/A196 b/data/raw/A196 new file mode 100644 index 0000000..23df114 Binary files /dev/null and b/data/raw/A196 differ diff --git a/data/raw/A197 b/data/raw/A197 new file mode 100644 index 0000000..6433c5d Binary files /dev/null and b/data/raw/A197 differ diff --git a/data/raw/A198 b/data/raw/A198 new file mode 100644 index 0000000..22d689f Binary files /dev/null and b/data/raw/A198 differ diff --git a/data/raw/A199 b/data/raw/A199 new file mode 100644 index 0000000..c3bab20 Binary files /dev/null and b/data/raw/A199 differ diff --git a/data/raw/A2 b/data/raw/A2 new file mode 100644 index 0000000..167be6e Binary files /dev/null and b/data/raw/A2 differ diff --git a/data/raw/A20 b/data/raw/A20 new file mode 100644 index 0000000..e69c32d Binary files /dev/null and b/data/raw/A20 differ diff --git a/data/raw/A200 b/data/raw/A200 new file mode 100644 index 0000000..8e8e069 Binary files /dev/null and b/data/raw/A200 differ diff --git a/data/raw/A201 b/data/raw/A201 new file mode 100644 index 0000000..3a4884f Binary files /dev/null and b/data/raw/A201 differ diff --git a/data/raw/A202 b/data/raw/A202 new file mode 100644 index 0000000..f329ac2 Binary files /dev/null and b/data/raw/A202 differ diff --git a/data/raw/A203 b/data/raw/A203 new file mode 100644 index 0000000..47f942b Binary files /dev/null and b/data/raw/A203 differ diff --git a/data/raw/A204 b/data/raw/A204 new file mode 100644 index 0000000..3551bba Binary files /dev/null and b/data/raw/A204 differ diff --git a/data/raw/A205 b/data/raw/A205 new file mode 100644 index 0000000..b73f499 Binary files /dev/null and b/data/raw/A205 differ diff --git a/data/raw/A206 b/data/raw/A206 new file mode 100644 index 0000000..2584593 Binary files /dev/null and b/data/raw/A206 differ diff --git a/data/raw/A207 b/data/raw/A207 new file mode 100644 index 0000000..ff07d6e Binary files /dev/null and b/data/raw/A207 differ diff --git a/data/raw/A208 b/data/raw/A208 new file mode 100644 index 0000000..9518902 Binary files /dev/null and b/data/raw/A208 differ diff --git a/data/raw/A209 b/data/raw/A209 new file mode 100644 index 0000000..990f0de Binary files /dev/null and b/data/raw/A209 differ diff --git a/data/raw/A21 b/data/raw/A21 new file mode 100644 index 0000000..75cfa56 Binary files /dev/null and b/data/raw/A21 differ diff --git a/data/raw/A210 b/data/raw/A210 new file mode 100644 index 0000000..1cda247 Binary files /dev/null and b/data/raw/A210 differ diff --git a/data/raw/A211 b/data/raw/A211 new file mode 100644 index 0000000..1a83995 Binary files /dev/null and b/data/raw/A211 differ diff --git a/data/raw/A212 b/data/raw/A212 new file mode 100644 index 0000000..14a518b Binary files /dev/null and b/data/raw/A212 differ diff --git a/data/raw/A213 b/data/raw/A213 new file mode 100644 index 0000000..a8b5afe Binary files /dev/null and b/data/raw/A213 differ diff --git a/data/raw/A214 b/data/raw/A214 new file mode 100644 index 0000000..ab2e9a4 Binary files /dev/null and b/data/raw/A214 differ diff --git a/data/raw/A215 b/data/raw/A215 new file mode 100644 index 0000000..f77a68c Binary files /dev/null and b/data/raw/A215 differ diff --git a/data/raw/A216 b/data/raw/A216 new file mode 100644 index 0000000..a5fb0f6 Binary files /dev/null and b/data/raw/A216 differ diff --git a/data/raw/A217 b/data/raw/A217 new file mode 100644 index 0000000..6819eab Binary files /dev/null and b/data/raw/A217 differ diff --git a/data/raw/A218 b/data/raw/A218 new file mode 100644 index 0000000..6c92fdf Binary files /dev/null and b/data/raw/A218 differ diff --git a/data/raw/A219 b/data/raw/A219 new file mode 100644 index 0000000..9e2abb8 Binary files /dev/null and b/data/raw/A219 differ diff --git a/data/raw/A22 b/data/raw/A22 new file mode 100644 index 0000000..3d59b4d Binary files /dev/null and b/data/raw/A22 differ diff --git a/data/raw/A220 b/data/raw/A220 new file mode 100644 index 0000000..d72ff07 Binary files /dev/null and b/data/raw/A220 differ diff --git a/data/raw/A221 b/data/raw/A221 new file mode 100644 index 0000000..f3ea0a3 Binary files /dev/null and b/data/raw/A221 differ diff --git a/data/raw/A222 b/data/raw/A222 new file mode 100644 index 0000000..bace53c Binary files /dev/null and b/data/raw/A222 differ diff --git a/data/raw/A223 b/data/raw/A223 new file mode 100644 index 0000000..ce6951c Binary files /dev/null and b/data/raw/A223 differ diff --git a/data/raw/A224 b/data/raw/A224 new file mode 100644 index 0000000..84dc04d Binary files /dev/null and b/data/raw/A224 differ diff --git a/data/raw/A225 b/data/raw/A225 new file mode 100644 index 0000000..f12e3bc Binary files /dev/null and b/data/raw/A225 differ diff --git a/data/raw/A226 b/data/raw/A226 new file mode 100644 index 0000000..766fe87 Binary files /dev/null and b/data/raw/A226 differ diff --git a/data/raw/A227 b/data/raw/A227 new file mode 100644 index 0000000..811305b Binary files /dev/null and b/data/raw/A227 differ diff --git a/data/raw/A228 b/data/raw/A228 new file mode 100644 index 0000000..147b921 Binary files /dev/null and b/data/raw/A228 differ diff --git a/data/raw/A229 b/data/raw/A229 new file mode 100644 index 0000000..acbed28 Binary files /dev/null and b/data/raw/A229 differ diff --git a/data/raw/A23 b/data/raw/A23 new file mode 100644 index 0000000..b5db4a3 Binary files /dev/null and b/data/raw/A23 differ diff --git a/data/raw/A230 b/data/raw/A230 new file mode 100644 index 0000000..9168e35 Binary files /dev/null and b/data/raw/A230 differ diff --git a/data/raw/A231 b/data/raw/A231 new file mode 100644 index 0000000..269a72d Binary files /dev/null and b/data/raw/A231 differ diff --git a/data/raw/A232 b/data/raw/A232 new file mode 100644 index 0000000..18251f0 Binary files /dev/null and b/data/raw/A232 differ diff --git a/data/raw/A233 b/data/raw/A233 new file mode 100644 index 0000000..ad6795f Binary files /dev/null and b/data/raw/A233 differ diff --git a/data/raw/A234 b/data/raw/A234 new file mode 100644 index 0000000..a70dc99 Binary files /dev/null and b/data/raw/A234 differ diff --git a/data/raw/A235 b/data/raw/A235 new file mode 100644 index 0000000..4fb2315 Binary files /dev/null and b/data/raw/A235 differ diff --git a/data/raw/A236 b/data/raw/A236 new file mode 100644 index 0000000..fbc01d0 Binary files /dev/null and b/data/raw/A236 differ diff --git a/data/raw/A237 b/data/raw/A237 new file mode 100644 index 0000000..cc7e840 Binary files /dev/null and b/data/raw/A237 differ diff --git a/data/raw/A24 b/data/raw/A24 new file mode 100644 index 0000000..e05a95e Binary files /dev/null and b/data/raw/A24 differ diff --git a/data/raw/A25 b/data/raw/A25 new file mode 100644 index 0000000..10603ff Binary files /dev/null and b/data/raw/A25 differ diff --git a/data/raw/A26 b/data/raw/A26 new file mode 100644 index 0000000..a7056a2 Binary files /dev/null and b/data/raw/A26 differ diff --git a/data/raw/A27 b/data/raw/A27 new file mode 100644 index 0000000..6654bce Binary files /dev/null and b/data/raw/A27 differ diff --git a/data/raw/A28 b/data/raw/A28 new file mode 100644 index 0000000..fd99276 Binary files /dev/null and b/data/raw/A28 differ diff --git a/data/raw/A29 b/data/raw/A29 new file mode 100644 index 0000000..2f7c997 Binary files /dev/null and b/data/raw/A29 differ diff --git a/data/raw/A3 b/data/raw/A3 new file mode 100644 index 0000000..8ca8eb7 Binary files /dev/null and b/data/raw/A3 differ diff --git a/data/raw/A30 b/data/raw/A30 new file mode 100644 index 0000000..18ac799 Binary files /dev/null and b/data/raw/A30 differ diff --git a/data/raw/A31 b/data/raw/A31 new file mode 100644 index 0000000..855ad73 Binary files /dev/null and b/data/raw/A31 differ diff --git a/data/raw/A32 b/data/raw/A32 new file mode 100644 index 0000000..e0bce5a Binary files /dev/null and b/data/raw/A32 differ diff --git a/data/raw/A33 b/data/raw/A33 new file mode 100644 index 0000000..4475685 Binary files /dev/null and b/data/raw/A33 differ diff --git a/data/raw/A34 b/data/raw/A34 new file mode 100644 index 0000000..03783c2 Binary files /dev/null and b/data/raw/A34 differ diff --git a/data/raw/A35 b/data/raw/A35 new file mode 100644 index 0000000..dd4f655 Binary files /dev/null and b/data/raw/A35 differ diff --git a/data/raw/A36 b/data/raw/A36 new file mode 100644 index 0000000..a4ac419 Binary files /dev/null and b/data/raw/A36 differ diff --git a/data/raw/A37 b/data/raw/A37 new file mode 100644 index 0000000..1738736 Binary files /dev/null and b/data/raw/A37 differ diff --git a/data/raw/A38 b/data/raw/A38 new file mode 100644 index 0000000..b1126cb Binary files /dev/null and b/data/raw/A38 differ diff --git a/data/raw/A39 b/data/raw/A39 new file mode 100644 index 0000000..b4126b2 Binary files /dev/null and b/data/raw/A39 differ diff --git a/data/raw/A4 b/data/raw/A4 new file mode 100644 index 0000000..34bcdce Binary files /dev/null and b/data/raw/A4 differ diff --git a/data/raw/A40 b/data/raw/A40 new file mode 100644 index 0000000..323c5d1 Binary files /dev/null and b/data/raw/A40 differ diff --git a/data/raw/A41 b/data/raw/A41 new file mode 100644 index 0000000..82888ab Binary files /dev/null and b/data/raw/A41 differ diff --git a/data/raw/A42 b/data/raw/A42 new file mode 100644 index 0000000..6b0f54d Binary files /dev/null and b/data/raw/A42 differ diff --git a/data/raw/A43 b/data/raw/A43 new file mode 100644 index 0000000..929eae3 Binary files /dev/null and b/data/raw/A43 differ diff --git a/data/raw/A44 b/data/raw/A44 new file mode 100644 index 0000000..91bcd62 Binary files /dev/null and b/data/raw/A44 differ diff --git a/data/raw/A45 b/data/raw/A45 new file mode 100644 index 0000000..bc5a9e3 Binary files /dev/null and b/data/raw/A45 differ diff --git a/data/raw/A46 b/data/raw/A46 new file mode 100644 index 0000000..82fd03b Binary files /dev/null and b/data/raw/A46 differ diff --git a/data/raw/A47 b/data/raw/A47 new file mode 100644 index 0000000..1b9a0c9 Binary files /dev/null and b/data/raw/A47 differ diff --git a/data/raw/A48 b/data/raw/A48 new file mode 100644 index 0000000..230b73a Binary files /dev/null and b/data/raw/A48 differ diff --git a/data/raw/A49 b/data/raw/A49 new file mode 100644 index 0000000..10e8f46 Binary files /dev/null and b/data/raw/A49 differ diff --git a/data/raw/A5 b/data/raw/A5 new file mode 100644 index 0000000..9f43d77 Binary files /dev/null and b/data/raw/A5 differ diff --git a/data/raw/A50 b/data/raw/A50 new file mode 100644 index 0000000..a814642 Binary files /dev/null and b/data/raw/A50 differ diff --git a/data/raw/A51 b/data/raw/A51 new file mode 100644 index 0000000..19117b4 Binary files /dev/null and b/data/raw/A51 differ diff --git a/data/raw/A52 b/data/raw/A52 new file mode 100644 index 0000000..f70ad14 Binary files /dev/null and b/data/raw/A52 differ diff --git a/data/raw/A53 b/data/raw/A53 new file mode 100644 index 0000000..ae854aa Binary files /dev/null and b/data/raw/A53 differ diff --git a/data/raw/A54 b/data/raw/A54 new file mode 100644 index 0000000..7e69517 Binary files /dev/null and b/data/raw/A54 differ diff --git a/data/raw/A55 b/data/raw/A55 new file mode 100644 index 0000000..612214e Binary files /dev/null and b/data/raw/A55 differ diff --git a/data/raw/A56 b/data/raw/A56 new file mode 100644 index 0000000..242a3d2 Binary files /dev/null and b/data/raw/A56 differ diff --git a/data/raw/A57 b/data/raw/A57 new file mode 100644 index 0000000..f6609cf Binary files /dev/null and b/data/raw/A57 differ diff --git a/data/raw/A58 b/data/raw/A58 new file mode 100644 index 0000000..bdd6c17 Binary files /dev/null and b/data/raw/A58 differ diff --git a/data/raw/A59 b/data/raw/A59 new file mode 100644 index 0000000..03e1338 Binary files /dev/null and b/data/raw/A59 differ diff --git a/data/raw/A6 b/data/raw/A6 new file mode 100644 index 0000000..6ca12bc Binary files /dev/null and b/data/raw/A6 differ diff --git a/data/raw/A60 b/data/raw/A60 new file mode 100644 index 0000000..49291d2 Binary files /dev/null and b/data/raw/A60 differ diff --git a/data/raw/A61 b/data/raw/A61 new file mode 100644 index 0000000..4b63c0e Binary files /dev/null and b/data/raw/A61 differ diff --git a/data/raw/A62 b/data/raw/A62 new file mode 100644 index 0000000..3f4cf45 Binary files /dev/null and b/data/raw/A62 differ diff --git a/data/raw/A63 b/data/raw/A63 new file mode 100644 index 0000000..015ee20 Binary files /dev/null and b/data/raw/A63 differ diff --git a/data/raw/A64 b/data/raw/A64 new file mode 100644 index 0000000..5cf5f3d Binary files /dev/null and b/data/raw/A64 differ diff --git a/data/raw/A65 b/data/raw/A65 new file mode 100644 index 0000000..88b4f89 Binary files /dev/null and b/data/raw/A65 differ diff --git a/data/raw/A66 b/data/raw/A66 new file mode 100644 index 0000000..29790c6 Binary files /dev/null and b/data/raw/A66 differ diff --git a/data/raw/A67 b/data/raw/A67 new file mode 100644 index 0000000..2e54ec8 Binary files /dev/null and b/data/raw/A67 differ diff --git a/data/raw/A68 b/data/raw/A68 new file mode 100644 index 0000000..c6c699e Binary files /dev/null and b/data/raw/A68 differ diff --git a/data/raw/A69 b/data/raw/A69 new file mode 100644 index 0000000..37216e9 Binary files /dev/null and b/data/raw/A69 differ diff --git a/data/raw/A7 b/data/raw/A7 new file mode 100644 index 0000000..d5cf11f Binary files /dev/null and b/data/raw/A7 differ diff --git a/data/raw/A70 b/data/raw/A70 new file mode 100644 index 0000000..a414310 Binary files /dev/null and b/data/raw/A70 differ diff --git a/data/raw/A71 b/data/raw/A71 new file mode 100644 index 0000000..715113b Binary files /dev/null and b/data/raw/A71 differ diff --git a/data/raw/A72 b/data/raw/A72 new file mode 100644 index 0000000..13dc1ac Binary files /dev/null and b/data/raw/A72 differ diff --git a/data/raw/A73 b/data/raw/A73 new file mode 100644 index 0000000..5091685 Binary files /dev/null and b/data/raw/A73 differ diff --git a/data/raw/A74 b/data/raw/A74 new file mode 100644 index 0000000..f116ab1 Binary files /dev/null and b/data/raw/A74 differ diff --git a/data/raw/A75 b/data/raw/A75 new file mode 100644 index 0000000..b64a8ea Binary files /dev/null and b/data/raw/A75 differ diff --git a/data/raw/A76 b/data/raw/A76 new file mode 100644 index 0000000..99f3f32 Binary files /dev/null and b/data/raw/A76 differ diff --git a/data/raw/A77 b/data/raw/A77 new file mode 100644 index 0000000..879e8f8 Binary files /dev/null and b/data/raw/A77 differ diff --git a/data/raw/A78 b/data/raw/A78 new file mode 100644 index 0000000..3de60cc Binary files /dev/null and b/data/raw/A78 differ diff --git a/data/raw/A79 b/data/raw/A79 new file mode 100644 index 0000000..ddbe006 Binary files /dev/null and b/data/raw/A79 differ diff --git a/data/raw/A8 b/data/raw/A8 new file mode 100644 index 0000000..e15b937 Binary files /dev/null and b/data/raw/A8 differ diff --git a/data/raw/A80 b/data/raw/A80 new file mode 100644 index 0000000..70a8a64 Binary files /dev/null and b/data/raw/A80 differ diff --git a/data/raw/A81 b/data/raw/A81 new file mode 100644 index 0000000..42fabc2 Binary files /dev/null and b/data/raw/A81 differ diff --git a/data/raw/A82 b/data/raw/A82 new file mode 100644 index 0000000..c689044 Binary files /dev/null and b/data/raw/A82 differ diff --git a/data/raw/A83 b/data/raw/A83 new file mode 100644 index 0000000..7c07e4d Binary files /dev/null and b/data/raw/A83 differ diff --git a/data/raw/A84 b/data/raw/A84 new file mode 100644 index 0000000..844e8df Binary files /dev/null and b/data/raw/A84 differ diff --git a/data/raw/A85 b/data/raw/A85 new file mode 100644 index 0000000..8461823 Binary files /dev/null and b/data/raw/A85 differ diff --git a/data/raw/A86 b/data/raw/A86 new file mode 100644 index 0000000..4e3935a Binary files /dev/null and b/data/raw/A86 differ diff --git a/data/raw/A87 b/data/raw/A87 new file mode 100644 index 0000000..5f730cb Binary files /dev/null and b/data/raw/A87 differ diff --git a/data/raw/A88 b/data/raw/A88 new file mode 100644 index 0000000..94adccb Binary files /dev/null and b/data/raw/A88 differ diff --git a/data/raw/A89 b/data/raw/A89 new file mode 100644 index 0000000..74931bc Binary files /dev/null and b/data/raw/A89 differ diff --git a/data/raw/A9 b/data/raw/A9 new file mode 100644 index 0000000..178d3b2 Binary files /dev/null and b/data/raw/A9 differ diff --git a/data/raw/A90 b/data/raw/A90 new file mode 100644 index 0000000..f522f54 Binary files /dev/null and b/data/raw/A90 differ diff --git a/data/raw/A91 b/data/raw/A91 new file mode 100644 index 0000000..508c556 Binary files /dev/null and b/data/raw/A91 differ diff --git a/data/raw/A92 b/data/raw/A92 new file mode 100644 index 0000000..0202ebc Binary files /dev/null and b/data/raw/A92 differ diff --git a/data/raw/A93 b/data/raw/A93 new file mode 100644 index 0000000..0115040 Binary files /dev/null and b/data/raw/A93 differ diff --git a/data/raw/A94 b/data/raw/A94 new file mode 100644 index 0000000..835a3d8 Binary files /dev/null and b/data/raw/A94 differ diff --git a/data/raw/A95 b/data/raw/A95 new file mode 100644 index 0000000..76e933e Binary files /dev/null and b/data/raw/A95 differ diff --git a/data/raw/A96 b/data/raw/A96 new file mode 100644 index 0000000..d54a0ec Binary files /dev/null and b/data/raw/A96 differ diff --git a/data/raw/A97 b/data/raw/A97 new file mode 100644 index 0000000..c88f610 Binary files /dev/null and b/data/raw/A97 differ diff --git a/data/raw/A98 b/data/raw/A98 new file mode 100644 index 0000000..91ca5ce Binary files /dev/null and b/data/raw/A98 differ diff --git a/data/raw/A99 b/data/raw/A99 new file mode 100644 index 0000000..3a324a0 Binary files /dev/null and b/data/raw/A99 differ diff --git a/data/raw/CAM1.DAT b/data/raw/CAM1.DAT new file mode 100644 index 0000000..d79f547 Binary files /dev/null and b/data/raw/CAM1.DAT differ diff --git a/data/raw/CAM2.DAT b/data/raw/CAM2.DAT new file mode 100644 index 0000000..142d0f7 Binary files /dev/null and b/data/raw/CAM2.DAT differ diff --git a/data/raw/MakeRootBin_std.C b/data/raw/MakeRootBin_std.C new file mode 100644 index 0000000..2c48729 --- /dev/null +++ b/data/raw/MakeRootBin_std.C @@ -0,0 +1,100 @@ +#include +#define File "Spectra_A.root" +#define N 10 +#define prefix "a_series/A" +void MakeASCII(TH1D* h){ + std::string name = h->GetName(); + name = "c_series_ascii/"+name+".txt"; + std::ofstream out(name); + for(int i = 0; i< h->GetXaxis()->GetNbins();i++){ + out<GetBinContent(i)<SetBinContent(i,buffer[i])/*std::cout<Clone("total_spectrum"); + h_tot1 = (TH1D*) h1->Clone("total_spectrum1"); + h_tot2 = (TH1D*) h1->Clone("total_spectrum2"); + h_tot->Reset(); + h_tot1->Reset(); + h_tot2->Reset(); + } + h1->Add(h2,-1); +// h->Add(ReadFile(n2.c_str()),-1); +// h1->SetName("calib"); +// h1->Write(); + h1->Write(); + h_cnt->SetBinContent(i,h1->Integral(1427,2760)); + h_cnt2->SetBinContent(i,h1->Integral(0,100)); + h_tot->Add(h1); + if(i<96) h_tot1->Add(h1); + if(i>95 && i < 191) h_tot2->Add(h1); + // h3->Write(); + // MakeASCII(h1); + MakeASCII(h1); +// MakeASCII(h3); + } + h_tot->Write(); + h_tot1->Write(); + h_tot2->Write(); + + h_cnt->Write(); +// TH1D* h_cal = ReadFile("a_series/CAM2.DAT","calib"); +// h_cal->Write(); +// f->Close(); +} + + diff --git a/exp_data/raw_reader.py b/exp_data/raw_reader.py new file mode 100644 index 0000000..990a8d7 --- /dev/null +++ b/exp_data/raw_reader.py @@ -0,0 +1,284 @@ +""" +Raw binary spectrum reader for 4096-channel MCA data. + +Reads binary files with 128-byte header + 4096 channels of int32 counts. +Used for both Tc-99 beta spectra and Am-241 calibration sources. +""" + +from __future__ import annotations + +import struct +from pathlib import Path +from typing import Optional + +import numpy as np +from scipy.signal import find_peaks + +from exp_data.spectrum import ExpSpectrum + +# Binary format constants +HEADER_SIZE = 128 # bytes +CHANNEL_SIZE = 4 # int32 +DEFAULT_N_CHANNELS = 4096 +# 16512 = 128 + 4096 * 4 +FILE_SIZE = HEADER_SIZE + DEFAULT_N_CHANNELS * CHANNEL_SIZE + + +def read_raw_spectrum( + filepath: str | Path, + n_channels: int = DEFAULT_N_CHANNELS, + energy_keV: Optional[np.ndarray] = None, + run_id: Optional[str] = None, + source: Optional[str] = None, + live_time_sec: Optional[float] = None, + metadata: Optional[dict] = None, +) -> ExpSpectrum: + """Read a raw binary spectrum file. + + Parameters + ---------- + filepath + Path to the binary spectrum file. + n_channels + Number of energy channels (default 4096). + energy_keV + Energy calibration array (n_channels,). If None, uses channel indices. + run_id + Run identifier string. + source + Source identifier (e.g. 'Tc99', 'Am241'). + live_time_sec + Live acquisition time in seconds. + metadata + Additional metadata dict. + + Returns + ------- + ExpSpectrum + Parsed spectrum with metadata. + """ + filepath = Path(filepath) + if not filepath.exists(): + raise FileNotFoundError(f"Spectrum file not found: {filepath}") + + file_size = filepath.stat().st_size + expected = HEADER_SIZE + n_channels * CHANNEL_SIZE + if file_size != expected: + raise ValueError( + f"File size {file_size} != expected {expected} " + f"(header={HEADER_SIZE} + {n_channels}ch * {CHANNEL_SIZE}B)" + ) + + with open(filepath, "rb") as f: + # Skip header + f.seek(HEADER_SIZE) + counts = np.fromfile(f, dtype=np.int32, count=n_channels) + + if energy_keV is None: + energy_keV = np.arange(n_channels, dtype=np.float64) + + return ExpSpectrum( + energies=energy_keV, + counts=counts.astype(np.float64), + metadata=metadata or {}, + run_id=run_id, + source=source, + live_time=live_time_sec, + ) + + +def subtract_spectra( + cumulative_a: ExpSpectrum, + cumulative_b: ExpSpectrum, + run_id: Optional[str] = None, +) -> ExpSpectrum: + """Subtract two cumulative spectra to get the incremental run. + + Both spectra must have the same number of channels. + Result = A - B (where A is the later cumulative measurement). + + Parameters + ---------- + cumulative_a + Later cumulative spectrum (larger time). + cumulative_b + Earlier cumulative spectrum (smaller time). + run_id + Run ID for the difference spectrum. + + Returns + ------- + ExpSpectrum + The difference spectrum (A - B). + """ + assert len(cumulative_a.counts) == len(cumulative_b.counts), ( + f"Spectra must have same channel count: " + f"{len(cumulative_a.counts)} vs {len(cumulative_b.counts)}" + ) + + diff_counts = cumulative_a.counts - cumulative_b.counts + # Propagate errors: σ_diff = sqrt(σ_a² + σ_b²) + diff_errors = np.sqrt(cumulative_a.errors**2 + cumulative_b.errors**2) + + return ExpSpectrum( + energies=cumulative_a.energies.copy(), + counts=diff_counts, + errors=diff_errors, + metadata={ + **cumulative_a.metadata, + "operation": "subtract", + "parent_a": cumulative_a.run_id, + "parent_b": cumulative_b.run_id, + }, + run_id=run_id, + source=cumulative_a.source, + ) + + +def calibrate_from_am241( + filepath: str | Path, + known_peaks: dict[float, int] | None = None, + n_channels: int = DEFAULT_N_CHANNELS, +) -> tuple[float, float]: + """Calibrate energy scale using Am-241 calibration source. + + Reads the Am-241 spectrum, finds prominent peaks, matches them + to known gamma lines, and fits a linear energy calibration. + + Parameters + ---------- + filepath + Path to the Am-241 binary file (CAM1.DAT or CAM2.DAT). + known_peaks + Mapping of energy_keV -> expected channel. If None, auto-detects + Am-241 peaks at 13.8, 17.8, 26.3, 59.54 keV. + n_channels + Number of channels. + + Returns + ------- + (offset_keV, gain_keV_per_ch) + Linear calibration: E = offset + gain * channel + """ + filepath = Path(filepath) + with open(filepath, "rb") as f: + f.read(128) # skip header + counts = np.array(struct.unpack(f"{n_channels}i", f.read(n_channels * 4)), dtype=np.int64) + + # Exclude endpoint region (last 200 channels) + counts_no_end = counts.copy() + counts_no_end[-200:] = 0 + + peaks, props = find_peaks(counts_no_end, height=10, distance=10) + peak_energies = np.array(peaks) + peak_heights = props["peak_heights"] + + # Known Am-241 gamma lines (keV) + am241_lines = {13.8: None, 17.8: None, 26.3: None, 59.54: None} + if known_peaks: + am241_lines = known_peaks + else: + # Find peaks near expected channels + for E, ch in list(am241_lines.items()): + if ch is None: + # Find the nearest peak + best = peak_energies[np.argmin(np.abs(peak_energies - E / 0.45))] # rough guess + am241_lines[E] = int(round(best)) + + # Use all identified peaks for calibration + energies = np.array(list(am241_lines.keys())) + channels = np.array(list(am241_lines.values())) + + # Linear fit + coeffs = np.polyfit(channels, energies, 1) + gain = coeffs[0] + offset = coeffs[1] + + return float(offset), float(gain) + + +def read_am241_calibration( + filepath: str | Path, + channel_energy_map: dict[int, float] | None = None, + n_channels: int = DEFAULT_N_CHANNELS, +) -> ExpSpectrum: + """Read Am-241 calibration spectrum. + + Parameters + ---------- + filepath + Path to the binary calibration file (CAM1.DAT or CAM2.DAT). + channel_energy_map + Mapping of channel index -> energy_keV for known peaks. + If None, assumes linear calibration from channel indices. + n_channels + Number of channels. + + Returns + ------- + ExpSpectrum + Calibration spectrum. + """ + filepath = Path(filepath) + + # Am-241 known peaks (keV): 13.8, 17.8, 26.3, 59.54 + # The spectrum typically has a few prominent peaks + with open(filepath, "rb") as f: + header = f.read(128) + counts_raw = struct.unpack(f"{n_channels}i", f.read(n_channels * 4)) + + counts = np.array(counts_raw, dtype=np.float64) + energy_keV = np.arange(n_channels, dtype=np.float64) + + metadata = { + "source": "Am241", + "calibration_type": "energy", + "known_peaks_keV": [13.8, 17.8, 26.3, 59.54], + } + + return ExpSpectrum( + energies=energy_keV, + counts=counts, + metadata=metadata, + source="Am241", + ) + + +def get_run_files( + directory: str | Path, + prefix: str = "A", + sort_key: str = "natural", +) -> list[Path]: + """Get sorted list of run files in directory. + + Parameters + ---------- + directory + Directory containing run files. + prefix + Filename prefix (default 'A'). + sort_key + Sort method: 'natural' (A1, A2, ..., A10, A11) or 'lexicographic' (A1, A10, A100). + + Returns + ------- + list[Path] + Sorted file paths. + """ + directory = Path(directory) + runs = [f for f in directory.iterdir() if f.is_file() and f.name.startswith(prefix)] + + if sort_key == "natural": + runs.sort(key=lambda p: _natural_sort_key(p.name)) + else: + runs.sort(key=lambda p: p.name) + + return runs + + +def _natural_sort_key(s: str) -> list: + """Sort key for natural ordering: A1, A2, ..., A10, A100.""" + import re + + parts = re.split(r"(\d+)", s) + return [int(p) if p.isdigit() else p.lower() for p in parts] diff --git a/exp_data/spectrum.py b/exp_data/spectrum.py index ff701ae..5fd8314 100644 --- a/exp_data/spectrum.py +++ b/exp_data/spectrum.py @@ -58,15 +58,24 @@ class ExpSpectrum: "must have the same shape" ) assert np.all(self.energies >= 0), "Energies must be non-negative" - assert np.all(self.counts >= 0), "Counts must be non-negative" + + # Difference spectra (cumulative subtraction) can have negative counts + # in channels where the true count is zero and Poisson noise causes + # the earlier cumulative to slightly exceed the later one. + # This is normal and expected — errors propagate correctly. if self.errors is None: - # Poisson statistics: σ = √N (handle zero counts gracefully) - self.errors = np.sqrt(np.maximum(self.counts, 1.0)) + # Poisson statistics: σ = √N for positive counts + pos_mask = self.counts >= 0 + errors = np.zeros_like(self.counts) + errors[pos_mask] = np.sqrt(self.counts[pos_mask]) + neg_mask = ~pos_mask + if neg_mask.any(): + errors[neg_mask] = np.sqrt(np.abs(self.counts[neg_mask])) + self.errors = errors else: self.errors = np.asarray(self.errors, dtype=np.float64) assert self.errors.shape == self.counts.shape - assert np.all(self.errors > 0), "Errors must be positive" @property def n_channels(self) -> int: diff --git a/scripts/analyze_raw.py b/scripts/analyze_raw.py new file mode 100644 index 0000000..7a16aca --- /dev/null +++ b/scripts/analyze_raw.py @@ -0,0 +1,293 @@ +#!/usr/bin/env python3 +""" +Analyze raw Tc-99 beta spectra for rate stability and endpoint drift. + +Data is cumulative (no reset between runs), so each file contains all +events accumulated up to that point. To get individual ~1-hour runs, +subtract consecutive files: run_N = cumulative_N - cumulative_(N-1). + +Produces plots of: + - Total count rate vs run number + - Regional count rates (low-energy vs high-energy) + - Low-energy fraction vs run number + - Endpoint position vs run number +""" + +from __future__ import annotations + +import sys +from pathlib import Path + +import numpy as np +from scipy.stats import linregress + +from exp_data.raw_reader import ( + calibrate_from_am241, + get_run_files, + read_raw_spectrum, + subtract_spectra, +) + +# Energy calibration from Am-241 source: E = offset + gain * channel +# Determined automatically from known Am-241 gamma lines +CALIBRATION_FILE = "data/raw/CAM1.DAT" +_calib_offset, _calib_gain = calibrate_from_am241(CALIBRATION_FILE) +ENERGY_OFFSET = _calib_offset +ENERGY_GAIN = _calib_gain + +# Approximate Tc-99 endpoint for reference +TC99_ENDPOINT = 294.0 # keV + + +def channel_to_energy(ch: np.ndarray) -> np.ndarray: + """Convert channel index to energy in keV.""" + return ENERGY_OFFSET + ch * ENERGY_GAIN + + +def estimate_endpoint_from_counts( + counts: np.ndarray, + energies_keV: np.ndarray, + guess_endpoint: float = TC99_ENDPOINT, +) -> float: + """Estimate beta endpoint from spectrum using Kurie plot linear extrapolation. + + For allowed beta decay, the Kurie plot K(E) = sqrt(counts / (pWF)) is + linear near the endpoint and extrapolates to zero at E = Q-value. + We use a simplified Kurie plot (sqrt(counts)) since the phase space + factor is slowly varying compared to the sharp drop at the endpoint. + + Fits a line to the last ~10% of the spectrum (in the tail region + where counts are small but above background) and finds the x-intercept. + + Parameters + ---------- + counts : np.ndarray + Count spectrum (channel indices, not energies). + energies_keV : np.ndarray + Energy calibration for each channel. + guess_endpoint : float + Expected endpoint for clamping. + + Returns + ------- + float + Estimated endpoint energy in keV. + """ + # Exclude overflow channel (last channel is always saturated) + counts_work = counts[:-1] + energies_work = energies_keV[:-1] + + # Estimate background from the very tail (last 3%) + n_tail = max(10, int(len(counts_work) * 0.03)) + background = np.median(counts_work[-n_tail:]) + + # Select tail region: last 10% of spectrum, above background + n_tail_region = max(20, int(len(counts_work) * 0.10)) + E_tail = energies_work[-n_tail_region:] + c_tail = counts_work[-n_tail_region:] + + # Only keep channels above background + noise + mask = c_tail > (background + np.sqrt(background)) + if not mask.any(): + return guess_endpoint + + E_sel = E_tail[mask] + c_sel = c_tail[mask] + + # Kurie plot: K = sqrt(counts - background) + K = np.sqrt(np.maximum(c_sel - background, 0.01)) + + # Linear fit: K = a + b * E, endpoint = -a/b + try: + slope, intercept, _, _ = linregress(E_sel, K)[:4] + if slope < 0: + endpoint = -intercept / slope + # Clamp to reasonable range + endpoint = max(guess_endpoint - 30, min(guess_endpoint + 80, endpoint)) + return float(endpoint) + except (ValueError, ZeroDivisionError): + pass + + # Fallback: use the last channel above background + last_above = E_sel[np.where(c_sel > background)[0][-1]] + return float(last_above) + + +def compute_regional_rates(counts: np.ndarray, energies_keV: np.ndarray) -> dict: + """Compute count rates in different energy regions.""" + total = float(np.sum(counts)) + low_mask = energies_keV < 100 + high_mask = ~low_mask + + return { + "total": total, + "low_energy": float(np.sum(counts[low_mask])), + "high_energy": float(np.sum(counts[high_mask])), + "low_fraction": float(np.sum(counts[low_mask]) / total) if total > 0 else 0.0, + } + + +def main(): + """Main analysis pipeline.""" + data_dir = Path(__file__).parent.parent / "data" / "raw" + output_dir = Path(__file__).parent.parent / "output" + output_dir.mkdir(exist_ok=True) + + # Get run files sorted naturally (A1, A2, ..., A10, A100, ...) + run_files = get_run_files(data_dir, prefix="A") + if len(run_files) < 2: + print(f"Need at least 2 run files, found {len(run_files)}") + sys.exit(1) + + print(f"Found {len(run_files)} cumulative run files") + + # Step 1: Read all cumulative spectra + print("\nReading cumulative spectra...") + cumulative_specs = [] + for i, fpath in enumerate(run_files): + try: + spec = read_raw_spectrum( + fpath, + run_id=fpath.name, + source="Tc99", + ) + cumulative_specs.append(spec) + except (FileNotFoundError, ValueError) as e: + print(f" Skipping {fpath.name}: {e}") + continue + + if len(cumulative_specs) < 2: + print("Need at least 2 valid spectra") + sys.exit(1) + + print(f" Loaded {len(cumulative_specs)} cumulative spectra") + + # Step 2: Subtract consecutive runs to get individual ~1h runs + print("\nSubtracting consecutive runs...") + individual_runs = [] + for i in range(1, len(cumulative_specs)): + parent_a = cumulative_specs[i].run_id + parent_b = cumulative_specs[i - 1].run_id + diff = subtract_spectra( + cumulative_a=cumulative_specs[i], + cumulative_b=cumulative_specs[i - 1], + run_id=f"run_{i}", + ) + individual_runs.append(diff) + + print(f" Extracted {len(individual_runs)} individual runs") + + # Step 3: Analyze each run + print("\nAnalyzing individual runs...") + run_ids = [] + total_rates = [] + low_rates = [] + high_rates = [] + low_fractions = [] + endpoints = [] + + energies_keV = channel_to_energy(np.arange(len(individual_runs[0].counts))) + + for i, run in enumerate(individual_runs): + run_ids.append(i + 1) + rates = compute_regional_rates(run.counts, energies_keV) + endpoint = estimate_endpoint_from_counts(run.counts, energies_keV) + + total_rates.append(rates["total"]) + low_rates.append(rates["low_energy"]) + high_rates.append(rates["high_energy"]) + low_fractions.append(rates["low_fraction"]) + endpoints.append(endpoint) + + if (i + 1) % 50 == 0: + print(f" Analyzed {i + 1}/{len(individual_runs)} runs") + + run_ids = np.array(run_ids) + total_rates = np.array(total_rates) + low_rates = np.array(low_rates) + high_rates = np.array(high_rates) + low_fractions = np.array(low_fractions) + endpoints = np.array(endpoints) + + # Print summary + print(f"\n{'='*60}") + print(f"Analysis of {len(run_ids)} individual Tc-99 runs") + print(f"{'='*60}") + print(f"Run range: {run_ids.min()} - {run_ids.max()}") + print(f"Total counts: {total_rates.min():.0f} - {total_rates.max():.0f}") + print(f"Low-energy fraction: {low_fractions.min():.3f} - {low_fractions.max():.3f}") + print(f"Endpoint estimate: {endpoints.min():.1f} - {endpoints.max():.1f} keV") + + # Endpoint drift + if len(run_ids) > 10: + slope, intercept, r_val, _, _ = linregress(run_ids, endpoints) + print(f"\nEndpoint drift: {slope:.3f} keV/run (R²={r_val**2:.4f})") + print(f" Start (run 1): {intercept + slope * run_ids[0]:.1f} keV") + print(f" End (run {run_ids[-1]}): {intercept + slope * run_ids[-1]:.1f} keV") + + # Rate drift + slope, intercept, r_val, _, _ = linregress(run_ids, total_rates) + print(f"\nTotal count rate drift: {slope:.0f} counts/run (R²={r_val**2:.4f})") + + # Save results + results_file = output_dir / "rate_analysis.csv" + with open(results_file, "w") as f: + f.write("run,total_counts,low_energy_counts,high_energy_counts,low_fraction,endpoint_keV\n") + for i in range(len(run_ids)): + f.write( + f"{run_ids[i]},{total_rates[i]:.0f},{low_rates[i]:.0f}," + f"{high_rates[i]:.0f},{low_fractions[i]:.4f},{endpoints[i]:.1f}\n" + ) + print(f"\nResults saved to {results_file}") + + # Plot + try: + import matplotlib.pyplot as plt + + fig, axes = plt.subplots(2, 2, figsize=(14, 10)) + + # Total counts + axes[0, 0].plot(run_ids, total_rates, "k-", lw=1.5) + axes[0, 0].set_xlabel("Run number") + axes[0, 0].set_ylabel("Total counts") + axes[0, 0].set_title("Total count rate per run") + axes[0, 0].grid(True, alpha=0.3) + + # Low-energy fraction + axes[0, 1].plot(run_ids, low_fractions, "b-", lw=1.5) + axes[0, 1].set_xlabel("Run number") + axes[0, 1].set_ylabel("Low-energy fraction (<100 keV)") + axes[0, 1].set_title("Low-energy fraction drift") + axes[0, 1].grid(True, alpha=0.3) + + # Endpoint + axes[1, 0].plot(run_ids, endpoints, "r-", lw=1.5) + axes[1, 0].axhline( + TC99_ENDPOINT, color="gray", ls="--", + label=f"Tc-99 Q ≈ {TC99_ENDPOINT} keV", + ) + axes[1, 0].set_xlabel("Run number") + axes[1, 0].set_ylabel("Endpoint (keV)") + axes[1, 0].set_title("Endpoint position drift") + axes[1, 0].legend(fontsize=9) + axes[1, 0].grid(True, alpha=0.3) + + # Low vs high energy + axes[1, 1].plot(run_ids, low_rates, "b-", lw=1.5, label="<100 keV") + axes[1, 1].plot(run_ids, high_rates, "r-", lw=1.5, label=">100 keV") + axes[1, 1].set_xlabel("Run number") + axes[1, 1].set_ylabel("Counts") + axes[1, 1].set_title("Regional count rates") + axes[1, 1].legend(fontsize=9) + axes[1, 1].grid(True, alpha=0.3) + + plt.tight_layout() + plot_file = output_dir / "rate_analysis.png" + fig.savefig(plot_file, dpi=150, bbox_inches="tight") + print(f"Plot saved to {plot_file}") + except ImportError: + print("\nmatplotlib not available — skipping plot generation") + + +if __name__ == "__main__": + main()