numdaplot 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (474) hide show
  1. numdaplot/__init__.py +506 -0
  2. numdaplot/arrays/__init__.py +5 -0
  3. numdaplot/arrays/array.py +92 -0
  4. numdaplot/arrays/array_arithmetic.py +404 -0
  5. numdaplot/arrays/array_calculation.py +143 -0
  6. numdaplot/arrays/array_conversion.py +150 -0
  7. numdaplot/arrays/array_creation.py +371 -0
  8. numdaplot/arrays/array_data.py +281 -0
  9. numdaplot/arrays/array_layout.py +179 -0
  10. numdaplot/arrays/array_logic.py +227 -0
  11. numdaplot/arrays/array_reflected_arithmetic.py +334 -0
  12. numdaplot/arrays/array_refusals.py +339 -0
  13. numdaplot/arrays/array_selection.py +195 -0
  14. numdaplot/arrays/array_sorting.py +59 -0
  15. numdaplot/arrays/axis_number.py +58 -0
  16. numdaplot/arrays/calculation/__init__.py +5 -0
  17. numdaplot/arrays/calculation/counting_statistics.py +325 -0
  18. numdaplot/arrays/calculation/location_statistics.py +268 -0
  19. numdaplot/arrays/calculation/math_function_values.py +183 -0
  20. numdaplot/arrays/calculation/statistic_values.py +209 -0
  21. numdaplot/arrays/calculation/time_function_values.py +419 -0
  22. numdaplot/arrays/conversion/__init__.py +5 -0
  23. numdaplot/arrays/conversion/array_text.py +62 -0
  24. numdaplot/arrays/conversion/equality_check.py +72 -0
  25. numdaplot/arrays/conversion/python_values.py +70 -0
  26. numdaplot/arrays/conversion/time_text.py +290 -0
  27. numdaplot/arrays/creation/__init__.py +5 -0
  28. numdaplot/arrays/creation/date_parts.py +89 -0
  29. numdaplot/arrays/creation/date_parts_values.py +437 -0
  30. numdaplot/arrays/creation/distribution.py +54 -0
  31. numdaplot/arrays/creation/filled_values.py +58 -0
  32. numdaplot/arrays/creation/list_conversion.py +311 -0
  33. numdaplot/arrays/creation/list_shape.py +97 -0
  34. numdaplot/arrays/creation/normal.py +65 -0
  35. numdaplot/arrays/creation/numpy_conversion.py +149 -0
  36. numdaplot/arrays/creation/random_integers.py +104 -0
  37. numdaplot/arrays/creation/random_values.py +97 -0
  38. numdaplot/arrays/creation/range_values.py +73 -0
  39. numdaplot/arrays/creation/spacing.py +84 -0
  40. numdaplot/arrays/creation/spacing_values.py +63 -0
  41. numdaplot/arrays/creation/uniform.py +63 -0
  42. numdaplot/arrays/equality.py +68 -0
  43. numdaplot/arrays/layout/__init__.py +5 -0
  44. numdaplot/arrays/layout/sorting_values.py +113 -0
  45. numdaplot/arrays/layout/unique_values.py +49 -0
  46. numdaplot/arrays/mapping/__init__.py +5 -0
  47. numdaplot/arrays/mapping/mapped_values.py +286 -0
  48. numdaplot/arrays/mapping/unmatched.py +50 -0
  49. numdaplot/arrays/mapping/value_change.py +55 -0
  50. numdaplot/arrays/mapping/value_mapping.py +161 -0
  51. numdaplot/arrays/math_functions/__init__.py +5 -0
  52. numdaplot/arrays/math_functions/absolute.py +27 -0
  53. numdaplot/arrays/math_functions/cosine.py +28 -0
  54. numdaplot/arrays/math_functions/exponential.py +27 -0
  55. numdaplot/arrays/math_functions/logarithm.py +72 -0
  56. numdaplot/arrays/math_functions/math_function.py +58 -0
  57. numdaplot/arrays/math_functions/round.py +58 -0
  58. numdaplot/arrays/math_functions/sine.py +28 -0
  59. numdaplot/arrays/math_functions/square_root.py +27 -0
  60. numdaplot/arrays/operations/__init__.py +5 -0
  61. numdaplot/arrays/operations/boolean_operands.py +48 -0
  62. numdaplot/arrays/operations/combination.py +157 -0
  63. numdaplot/arrays/operations/float_errors.py +170 -0
  64. numdaplot/arrays/operations/integer_bounds.py +175 -0
  65. numdaplot/arrays/operations/integer_rules.py +397 -0
  66. numdaplot/arrays/operations/operand.py +139 -0
  67. numdaplot/arrays/operations/time_arithmetic.py +479 -0
  68. numdaplot/arrays/operations/time_bounds.py +286 -0
  69. numdaplot/arrays/operations/time_result_bounds.py +397 -0
  70. numdaplot/arrays/operations/transformation.py +54 -0
  71. numdaplot/arrays/operations/type_requirements.py +94 -0
  72. numdaplot/arrays/replacement.py +66 -0
  73. numdaplot/arrays/selection/__init__.py +5 -0
  74. numdaplot/arrays/selection/comparison_masks.py +131 -0
  75. numdaplot/arrays/selection/membership_masks.py +118 -0
  76. numdaplot/arrays/selection/missing_mask.py +50 -0
  77. numdaplot/arrays/selection/region_index.py +178 -0
  78. numdaplot/arrays/selection/replaced_values.py +120 -0
  79. numdaplot/arrays/selection/rule_mask.py +83 -0
  80. numdaplot/arrays/selection/time_reference.py +172 -0
  81. numdaplot/arrays/shape.py +74 -0
  82. numdaplot/arrays/type_match.py +51 -0
  83. numdaplot/data_types/__init__.py +5 -0
  84. numdaplot/data_types/library.py +57 -0
  85. numdaplot/data_types/numpy_mapping.py +207 -0
  86. numdaplot/data_types/pandas_mapping.py +114 -0
  87. numdaplot/data_types/time_of_day.py +292 -0
  88. numdaplot/data_types/type.py +224 -0
  89. numdaplot/data_types/value_family.py +149 -0
  90. numdaplot/data_types/value_type.py +147 -0
  91. numdaplot/dates/__init__.py +5 -0
  92. numdaplot/dates/custom_date_format.py +83 -0
  93. numdaplot/dates/date_format.py +120 -0
  94. numdaplot/dates/date_part.py +59 -0
  95. numdaplot/dates/date_part_unit.py +153 -0
  96. numdaplot/dates/date_period.py +57 -0
  97. numdaplot/dates/duration_in.py +58 -0
  98. numdaplot/dates/duration_unit.py +90 -0
  99. numdaplot/dates/period_unit.py +101 -0
  100. numdaplot/dates/time_function.py +56 -0
  101. numdaplot/dates/time_zone.py +68 -0
  102. numdaplot/dates/time_zone_change.py +71 -0
  103. numdaplot/dates/time_zone_mode.py +81 -0
  104. numdaplot/dates/to_duration.py +58 -0
  105. numdaplot/errors/__init__.py +7 -0
  106. numdaplot/errors/broadcast_warning.py +36 -0
  107. numdaplot/errors/calculation_warning.py +35 -0
  108. numdaplot/errors/cell_out_of_range_error.py +77 -0
  109. numdaplot/errors/column_not_found_error.py +64 -0
  110. numdaplot/errors/conflicting_settings_error.py +60 -0
  111. numdaplot/errors/dimension_error.py +62 -0
  112. numdaplot/errors/display_warning.py +32 -0
  113. numdaplot/errors/duplicate_column_error.py +82 -0
  114. numdaplot/errors/duplicate_label_error.py +55 -0
  115. numdaplot/errors/duplicate_statistic_error.py +55 -0
  116. numdaplot/errors/duplicate_value_error.py +54 -0
  117. numdaplot/errors/empty_array_error.py +55 -0
  118. numdaplot/errors/empty_list_error.py +52 -0
  119. numdaplot/errors/empty_region_error.py +34 -0
  120. numdaplot/errors/empty_text_error.py +34 -0
  121. numdaplot/errors/empty_total_error.py +62 -0
  122. numdaplot/errors/empty_values_error.py +34 -0
  123. numdaplot/errors/file_access_error.py +70 -0
  124. numdaplot/errors/file_exists_error.py +62 -0
  125. numdaplot/errors/file_not_found_error.py +56 -0
  126. numdaplot/errors/incompatible_charts_error.py +80 -0
  127. numdaplot/errors/incompatible_types_error.py +104 -0
  128. numdaplot/errors/integer_overflow_error.py +61 -0
  129. numdaplot/errors/invalid_base_error.py +52 -0
  130. numdaplot/errors/invalid_bin_width_error.py +66 -0
  131. numdaplot/errors/invalid_bounds_error.py +58 -0
  132. numdaplot/errors/invalid_chart_data_error.py +81 -0
  133. numdaplot/errors/invalid_color_count_error.py +63 -0
  134. numdaplot/errors/invalid_color_error.py +51 -0
  135. numdaplot/errors/invalid_column_name_error.py +52 -0
  136. numdaplot/errors/invalid_conversion_error.py +119 -0
  137. numdaplot/errors/invalid_count_error.py +61 -0
  138. numdaplot/errors/invalid_date_format_error.py +51 -0
  139. numdaplot/errors/invalid_deviation_error.py +52 -0
  140. numdaplot/errors/invalid_fraction_error.py +51 -0
  141. numdaplot/errors/invalid_label_count_error.py +61 -0
  142. numdaplot/errors/invalid_limits_error.py +111 -0
  143. numdaplot/errors/invalid_opacity_error.py +52 -0
  144. numdaplot/errors/invalid_point_size_error.py +52 -0
  145. numdaplot/errors/invalid_position_error.py +106 -0
  146. numdaplot/errors/invalid_resolution_error.py +51 -0
  147. numdaplot/errors/invalid_rotation_error.py +53 -0
  148. numdaplot/errors/invalid_seed_error.py +53 -0
  149. numdaplot/errors/invalid_separator_error.py +52 -0
  150. numdaplot/errors/invalid_shape_error.py +52 -0
  151. numdaplot/errors/invalid_sheet_name_error.py +54 -0
  152. numdaplot/errors/invalid_size_error.py +58 -0
  153. numdaplot/errors/invalid_step_error.py +77 -0
  154. numdaplot/errors/invalid_suffixes_error.py +61 -0
  155. numdaplot/errors/invalid_time_zone_change_error.py +63 -0
  156. numdaplot/errors/invalid_type_error.py +79 -0
  157. numdaplot/errors/irregular_list_error.py +36 -0
  158. numdaplot/errors/join_relation_error.py +183 -0
  159. numdaplot/errors/missing_dependency_error.py +58 -0
  160. numdaplot/errors/missing_type_error.py +36 -0
  161. numdaplot/errors/missing_value_error.py +62 -0
  162. numdaplot/errors/not_single_value_error.py +53 -0
  163. numdaplot/errors/numdaplot_error.py +25 -0
  164. numdaplot/errors/numdaplot_warning.py +34 -0
  165. numdaplot/errors/occupied_cell_error.py +63 -0
  166. numdaplot/errors/out_of_domain_error.py +70 -0
  167. numdaplot/errors/readability_warning.py +35 -0
  168. numdaplot/errors/refused_operation_error.py +64 -0
  169. numdaplot/errors/refused_setting_error.py +60 -0
  170. numdaplot/errors/rejected_dates.py +60 -0
  171. numdaplot/errors/repeated_key.py +36 -0
  172. numdaplot/errors/shape_mismatch_error.py +67 -0
  173. numdaplot/errors/time_overflow_error.py +131 -0
  174. numdaplot/errors/time_zone_mismatch_error.py +83 -0
  175. numdaplot/errors/unknown_time_zone_error.py +51 -0
  176. numdaplot/errors/unmatched_value_error.py +81 -0
  177. numdaplot/errors/unsupported_image_format_error.py +56 -0
  178. numdaplot/errors/unsupported_index_error.py +38 -0
  179. numdaplot/errors/unsupported_missing_error.py +129 -0
  180. numdaplot/errors/unsupported_type_error.py +62 -0
  181. numdaplot/errors/value_conversion_error.py +215 -0
  182. numdaplot/ordering/__init__.py +5 -0
  183. numdaplot/ordering/missing_position.py +46 -0
  184. numdaplot/ordering/order.py +46 -0
  185. numdaplot/package_version.py +36 -0
  186. numdaplot/plots/__init__.py +5 -0
  187. numdaplot/plots/chart_layer.py +47 -0
  188. numdaplot/plots/charts/__init__.py +5 -0
  189. numdaplot/plots/charts/bar_chart.py +98 -0
  190. numdaplot/plots/charts/bar_layout.py +58 -0
  191. numdaplot/plots/charts/bin_count.py +61 -0
  192. numdaplot/plots/charts/bin_width.py +78 -0
  193. numdaplot/plots/charts/box_chart.py +97 -0
  194. numdaplot/plots/charts/cell_values.py +61 -0
  195. numdaplot/plots/charts/chart.py +59 -0
  196. numdaplot/plots/charts/chart_settings.py +105 -0
  197. numdaplot/plots/charts/color_scale.py +147 -0
  198. numdaplot/plots/charts/heatmap_chart.py +92 -0
  199. numdaplot/plots/charts/histogram_chart.py +93 -0
  200. numdaplot/plots/charts/line_chart.py +100 -0
  201. numdaplot/plots/charts/line_type.py +75 -0
  202. numdaplot/plots/charts/marker_shape.py +113 -0
  203. numdaplot/plots/charts/missing_chart.py +60 -0
  204. numdaplot/plots/charts/missing_map_chart.py +27 -0
  205. numdaplot/plots/charts/orientation.py +58 -0
  206. numdaplot/plots/charts/outliers.py +49 -0
  207. numdaplot/plots/charts/percentages.py +55 -0
  208. numdaplot/plots/charts/pie_chart.py +87 -0
  209. numdaplot/plots/charts/scatter_chart.py +159 -0
  210. numdaplot/plots/charts/value_axis.py +66 -0
  211. numdaplot/plots/data/__init__.py +5 -0
  212. numdaplot/plots/data/array_values.py +128 -0
  213. numdaplot/plots/data/chart_data.py +143 -0
  214. numdaplot/plots/data/chart_values.py +109 -0
  215. numdaplot/plots/data/column_reading.py +468 -0
  216. numdaplot/plots/data/heatmap_values.py +63 -0
  217. numdaplot/plots/data/missing_cells.py +165 -0
  218. numdaplot/plots/data/pie_values.py +215 -0
  219. numdaplot/plots/data/point_values.py +249 -0
  220. numdaplot/plots/data/position_kind.py +83 -0
  221. numdaplot/plots/data/renamed_layers.py +340 -0
  222. numdaplot/plots/data/sample_values.py +160 -0
  223. numdaplot/plots/data/shown_columns.py +248 -0
  224. numdaplot/plots/data/table_values.py +256 -0
  225. numdaplot/plots/data/unique_labels.py +45 -0
  226. numdaplot/plots/drawing/__init__.py +5 -0
  227. numdaplot/plots/drawing/bar_drawing.py +316 -0
  228. numdaplot/plots/drawing/box_drawing.py +344 -0
  229. numdaplot/plots/drawing/cell_merging.py +237 -0
  230. numdaplot/plots/drawing/chart_texts.py +124 -0
  231. numdaplot/plots/drawing/color_bar.py +57 -0
  232. numdaplot/plots/drawing/color_scale_values.py +120 -0
  233. numdaplot/plots/drawing/default_labels.py +41 -0
  234. numdaplot/plots/drawing/drawn_chart.py +50 -0
  235. numdaplot/plots/drawing/grid_axes.py +75 -0
  236. numdaplot/plots/drawing/heatmap_drawing.py +313 -0
  237. numdaplot/plots/drawing/histogram_drawing.py +350 -0
  238. numdaplot/plots/drawing/label_room.py +344 -0
  239. numdaplot/plots/drawing/label_thinning.py +216 -0
  240. numdaplot/plots/drawing/layer_alignment.py +319 -0
  241. numdaplot/plots/drawing/layer_colors.py +123 -0
  242. numdaplot/plots/drawing/line_drawing.py +85 -0
  243. numdaplot/plots/drawing/marker_codes.py +20 -0
  244. numdaplot/plots/drawing/missing_drawing.py +360 -0
  245. numdaplot/plots/drawing/moment_period_formatter.py +253 -0
  246. numdaplot/plots/drawing/pie_drawing.py +185 -0
  247. numdaplot/plots/drawing/plot_axes.py +38 -0
  248. numdaplot/plots/drawing/plot_drawing.py +288 -0
  249. numdaplot/plots/drawing/plot_theme.py +45 -0
  250. numdaplot/plots/drawing/position_axis.py +278 -0
  251. numdaplot/plots/drawing/scatter_drawing.py +364 -0
  252. numdaplot/plots/drawing/series_colors.py +177 -0
  253. numdaplot/plots/drawing/size_inches.py +45 -0
  254. numdaplot/plots/drawing/style_drawing.py +410 -0
  255. numdaplot/plots/drawing/text_contrast.py +44 -0
  256. numdaplot/plots/drawing/tick_rotation.py +354 -0
  257. numdaplot/plots/drawing/time_axis.py +212 -0
  258. numdaplot/plots/drawing/whole_numbers.py +72 -0
  259. numdaplot/plots/figure/__init__.py +5 -0
  260. numdaplot/plots/figure/cell.py +95 -0
  261. numdaplot/plots/figure/figure.py +256 -0
  262. numdaplot/plots/figure/figure_drawing.py +99 -0
  263. numdaplot/plots/figure/figure_style.py +60 -0
  264. numdaplot/plots/figure/layout.py +71 -0
  265. numdaplot/plots/figure/placement.py +150 -0
  266. numdaplot/plots/layer_reading.py +166 -0
  267. numdaplot/plots/output/__init__.py +5 -0
  268. numdaplot/plots/output/image_saving.py +187 -0
  269. numdaplot/plots/output/plot_display.py +181 -0
  270. numdaplot/plots/output/shown_object.py +45 -0
  271. numdaplot/plots/overlay_checks.py +245 -0
  272. numdaplot/plots/plot.py +31 -0
  273. numdaplot/plots/plot_data.py +140 -0
  274. numdaplot/plots/plot_distribution_creation.py +237 -0
  275. numdaplot/plots/plot_output.py +124 -0
  276. numdaplot/plots/plot_overlays.py +273 -0
  277. numdaplot/plots/plot_overview_creation.py +195 -0
  278. numdaplot/plots/plot_series_creation.py +213 -0
  279. numdaplot/plots/style/__init__.py +5 -0
  280. numdaplot/plots/style/axis_settings.py +60 -0
  281. numdaplot/plots/style/color.py +168 -0
  282. numdaplot/plots/style/custom_color.py +65 -0
  283. numdaplot/plots/style/grid_lines.py +49 -0
  284. numdaplot/plots/style/image_options.py +71 -0
  285. numdaplot/plots/style/legend_position.py +149 -0
  286. numdaplot/plots/style/plot_style.py +136 -0
  287. numdaplot/plots/style/size.py +70 -0
  288. numdaplot/plots/style/size_unit.py +62 -0
  289. numdaplot/positions/__init__.py +5 -0
  290. numdaplot/positions/axis.py +54 -0
  291. numdaplot/positions/index.py +51 -0
  292. numdaplot/positions/range.py +90 -0
  293. numdaplot/positions/region.py +92 -0
  294. numdaplot/py.typed +0 -0
  295. numdaplot/ratios/__init__.py +5 -0
  296. numdaplot/ratios/fraction.py +40 -0
  297. numdaplot/ratios/measure.py +48 -0
  298. numdaplot/rules/__init__.py +5 -0
  299. numdaplot/rules/between.py +78 -0
  300. numdaplot/rules/bounds.py +83 -0
  301. numdaplot/rules/case.py +48 -0
  302. numdaplot/rules/contains.py +63 -0
  303. numdaplot/rules/equal.py +43 -0
  304. numdaplot/rules/greater.py +39 -0
  305. numdaplot/rules/greater_or_equal.py +38 -0
  306. numdaplot/rules/is_in.py +67 -0
  307. numdaplot/rules/is_missing.py +25 -0
  308. numdaplot/rules/is_present.py +25 -0
  309. numdaplot/rules/less.py +39 -0
  310. numdaplot/rules/less_or_equal.py +38 -0
  311. numdaplot/rules/not_equal.py +45 -0
  312. numdaplot/rules/rule.py +62 -0
  313. numdaplot/rules/rule_values.py +44 -0
  314. numdaplot/rules/value_rule.py +110 -0
  315. numdaplot/settings/__init__.py +5 -0
  316. numdaplot/settings/argument_types.py +327 -0
  317. numdaplot/settings/field_types.py +593 -0
  318. numdaplot/statistics/__init__.py +5 -0
  319. numdaplot/statistics/count.py +71 -0
  320. numdaplot/statistics/count_distinct.py +27 -0
  321. numdaplot/statistics/counted_missing.py +46 -0
  322. numdaplot/statistics/maximum.py +27 -0
  323. numdaplot/statistics/mean.py +27 -0
  324. numdaplot/statistics/median.py +27 -0
  325. numdaplot/statistics/minimum.py +27 -0
  326. numdaplot/statistics/most_frequent.py +27 -0
  327. numdaplot/statistics/most_frequent_count.py +27 -0
  328. numdaplot/statistics/quantile.py +61 -0
  329. numdaplot/statistics/standard_deviation.py +29 -0
  330. numdaplot/statistics/statistic.py +63 -0
  331. numdaplot/statistics/sum.py +27 -0
  332. numdaplot/tables/__init__.py +5 -0
  333. numdaplot/tables/aggregation/__init__.py +5 -0
  334. numdaplot/tables/aggregation/aggregated_frame.py +189 -0
  335. numdaplot/tables/aggregation/aggregation.py +97 -0
  336. numdaplot/tables/aggregation/calculation.py +123 -0
  337. numdaplot/tables/aggregation/result_column.py +108 -0
  338. numdaplot/tables/aggregation/row_groups.py +96 -0
  339. numdaplot/tables/aggregation/statistic_name.py +122 -0
  340. numdaplot/tables/columns/__init__.py +5 -0
  341. numdaplot/tables/columns/added_column.py +89 -0
  342. numdaplot/tables/columns/boolean_conversion.py +144 -0
  343. numdaplot/tables/columns/boolean_rule.py +59 -0
  344. numdaplot/tables/columns/bracket_end.py +50 -0
  345. numdaplot/tables/columns/bracket_names.py +346 -0
  346. numdaplot/tables/columns/bracketed_column.py +179 -0
  347. numdaplot/tables/columns/brackets.py +234 -0
  348. numdaplot/tables/columns/chosen_columns.py +55 -0
  349. numdaplot/tables/columns/column_choice.py +84 -0
  350. numdaplot/tables/columns/column_mode.py +64 -0
  351. numdaplot/tables/columns/column_names.py +186 -0
  352. numdaplot/tables/columns/conversion.py +103 -0
  353. numdaplot/tables/columns/converted_column.py +669 -0
  354. numdaplot/tables/columns/date_conversion.py +526 -0
  355. numdaplot/tables/columns/date_range.py +135 -0
  356. numdaplot/tables/columns/name_change.py +67 -0
  357. numdaplot/tables/columns/new_column.py +79 -0
  358. numdaplot/tables/columns/number_conversion.py +281 -0
  359. numdaplot/tables/columns/renamed_columns.py +60 -0
  360. numdaplot/tables/columns/renaming.py +81 -0
  361. numdaplot/tables/columns/text_conversion.py +70 -0
  362. numdaplot/tables/columns/time_conversion.py +313 -0
  363. numdaplot/tables/columns/time_zone_conversion.py +128 -0
  364. numdaplot/tables/conflict.py +68 -0
  365. numdaplot/tables/description/__init__.py +5 -0
  366. numdaplot/tables/description/described_frame.py +335 -0
  367. numdaplot/tables/description/description.py +155 -0
  368. numdaplot/tables/duplicates/__init__.py +5 -0
  369. numdaplot/tables/duplicates/deduplicated_frame.py +66 -0
  370. numdaplot/tables/duplicates/deduplication.py +88 -0
  371. numdaplot/tables/duplicates/keep.py +81 -0
  372. numdaplot/tables/files/__init__.py +5 -0
  373. numdaplot/tables/files/column_names.py +60 -0
  374. numdaplot/tables/files/csv_file.py +265 -0
  375. numdaplot/tables/files/csv_read_options.py +89 -0
  376. numdaplot/tables/files/csv_separator.py +41 -0
  377. numdaplot/tables/files/csv_write_options.py +79 -0
  378. numdaplot/tables/files/decimal_count.py +42 -0
  379. numdaplot/tables/files/encoding.py +82 -0
  380. numdaplot/tables/files/excel_file.py +171 -0
  381. numdaplot/tables/files/excel_read_options.py +79 -0
  382. numdaplot/tables/files/excel_sheet.py +50 -0
  383. numdaplot/tables/files/excel_time_cells.py +146 -0
  384. numdaplot/tables/files/excel_write_options.py +63 -0
  385. numdaplot/tables/files/file_access.py +152 -0
  386. numdaplot/tables/files/file_paths.py +106 -0
  387. numdaplot/tables/files/json_decimals.py +387 -0
  388. numdaplot/tables/files/json_file.py +203 -0
  389. numdaplot/tables/files/json_layout.py +63 -0
  390. numdaplot/tables/files/json_read_options.py +64 -0
  391. numdaplot/tables/files/json_write_options.py +71 -0
  392. numdaplot/tables/files/missing_texts.py +63 -0
  393. numdaplot/tables/files/optional_package.py +42 -0
  394. numdaplot/tables/files/pandas_backend.py +11 -0
  395. numdaplot/tables/files/parquet_file.py +91 -0
  396. numdaplot/tables/files/parquet_read_options.py +56 -0
  397. numdaplot/tables/files/sas_file.py +94 -0
  398. numdaplot/tables/files/sas_read_options.py +67 -0
  399. numdaplot/tables/files/stata_file.py +83 -0
  400. numdaplot/tables/files/stata_read_options.py +56 -0
  401. numdaplot/tables/files/xpt_read_options.py +65 -0
  402. numdaplot/tables/filtering/__init__.py +5 -0
  403. numdaplot/tables/filtering/checked_frame.py +60 -0
  404. numdaplot/tables/filtering/column_mask.py +71 -0
  405. numdaplot/tables/filtering/column_match.py +62 -0
  406. numdaplot/tables/filtering/condition.py +94 -0
  407. numdaplot/tables/filtering/filter.py +74 -0
  408. numdaplot/tables/filtering/filter_mode.py +67 -0
  409. numdaplot/tables/filtering/row_mask.py +152 -0
  410. numdaplot/tables/filtering/rule_moments.py +164 -0
  411. numdaplot/tables/frames/__init__.py +5 -0
  412. numdaplot/tables/frames/array_frame.py +95 -0
  413. numdaplot/tables/frames/cleaned_names.py +132 -0
  414. numdaplot/tables/frames/column.py +15 -0
  415. numdaplot/tables/frames/column_values.py +273 -0
  416. numdaplot/tables/frames/frame_equality.py +130 -0
  417. numdaplot/tables/frames/frame_normalization.py +459 -0
  418. numdaplot/tables/frames/named_column_errors.py +85 -0
  419. numdaplot/tables/frames/pandas_decimals.py +113 -0
  420. numdaplot/tables/frames/region_positions.py +113 -0
  421. numdaplot/tables/frames/table_text.py +222 -0
  422. numdaplot/tables/frames/time_columns.py +345 -0
  423. numdaplot/tables/frames/time_range_errors.py +117 -0
  424. numdaplot/tables/frames/time_zones.py +271 -0
  425. numdaplot/tables/joining/__init__.py +5 -0
  426. numdaplot/tables/joining/join.py +110 -0
  427. numdaplot/tables/joining/join_keys.py +367 -0
  428. numdaplot/tables/joining/join_mode.py +93 -0
  429. numdaplot/tables/joining/join_relation.py +149 -0
  430. numdaplot/tables/joining/join_suffixes.py +71 -0
  431. numdaplot/tables/joining/joined_frame.py +166 -0
  432. numdaplot/tables/joining/joined_names.py +107 -0
  433. numdaplot/tables/joining/joined_rows.py +235 -0
  434. numdaplot/tables/joining/key_types.py +57 -0
  435. numdaplot/tables/joining/relation.py +78 -0
  436. numdaplot/tables/missing/__init__.py +5 -0
  437. numdaplot/tables/missing/missing_count.py +59 -0
  438. numdaplot/tables/missing/missing_counts.py +214 -0
  439. numdaplot/tables/missing/missing_drop.py +98 -0
  440. numdaplot/tables/missing/missing_mode.py +63 -0
  441. numdaplot/tables/missing/missing_ratio.py +71 -0
  442. numdaplot/tables/missing/missing_removal.py +257 -0
  443. numdaplot/tables/missing/missing_summary.py +174 -0
  444. numdaplot/tables/missing/ratio_comparison.py +70 -0
  445. numdaplot/tables/pivot/__init__.py +5 -0
  446. numdaplot/tables/pivot/pivot_table.py +104 -0
  447. numdaplot/tables/pivot/pivoted_frame.py +244 -0
  448. numdaplot/tables/preview/__init__.py +5 -0
  449. numdaplot/tables/preview/notebook_display.py +238 -0
  450. numdaplot/tables/preview/preview.py +100 -0
  451. numdaplot/tables/preview/preview_rows.py +55 -0
  452. numdaplot/tables/preview/shown_columns.py +62 -0
  453. numdaplot/tables/preview/side.py +82 -0
  454. numdaplot/tables/sorting/__init__.py +5 -0
  455. numdaplot/tables/sorting/sort_key.py +71 -0
  456. numdaplot/tables/sorting/sorted_frame.py +81 -0
  457. numdaplot/tables/sorting/sorting.py +82 -0
  458. numdaplot/tables/table.py +71 -0
  459. numdaplot/tables/table_calculation.py +172 -0
  460. numdaplot/tables/table_columns.py +214 -0
  461. numdaplot/tables/table_conversion.py +351 -0
  462. numdaplot/tables/table_data.py +321 -0
  463. numdaplot/tables/table_display.py +56 -0
  464. numdaplot/tables/table_joining.py +80 -0
  465. numdaplot/tables/table_layout.py +105 -0
  466. numdaplot/tables/table_missing.py +146 -0
  467. numdaplot/tables/table_reading.py +451 -0
  468. numdaplot/tables/table_refusals.py +295 -0
  469. numdaplot/tables/table_selection.py +163 -0
  470. numdaplot/tables/table_writing.py +269 -0
  471. numdaplot-0.1.0.dist-info/METADATA +176 -0
  472. numdaplot-0.1.0.dist-info/RECORD +474 -0
  473. numdaplot-0.1.0.dist-info/WHEEL +4 -0
  474. numdaplot-0.1.0.dist-info/licenses/LICENSE +28 -0
@@ -0,0 +1,175 @@
1
+ """
2
+ Bounds of an integer result, found from the lowest and the highest values of its operands.
3
+
4
+ .. versionadded:: 0.1.0
5
+ """
6
+
7
+ import math
8
+ from typing import Any
9
+
10
+ import numpy
11
+ from numpy.typing import NDArray
12
+
13
+ # A power above this number of bits fits no integer type, and is not worth computing exactly.
14
+ LARGEST_COMPUTED_BITS = 65
15
+ BEYOND_EVERY_INTEGER = 2**LARGEST_COMPUTED_BITS
16
+
17
+
18
+ def find_value_bounds(values: NDArray[Any]) -> tuple[int, int]:
19
+ """
20
+ Return the lowest and the highest values of integers or booleans, as Python integers.
21
+
22
+ .. versionadded:: 0.1.0
23
+
24
+ Parameters
25
+ ----------
26
+ values
27
+ At least one integer or boolean.
28
+
29
+ Returns
30
+ -------
31
+ tuple[int, int]
32
+ The lowest and the highest values.
33
+
34
+ Examples
35
+ --------
36
+ >>> import numpy
37
+ >>> from numdaplot.arrays.operations.integer_bounds import find_value_bounds
38
+ >>> find_value_bounds(numpy.array([3, -1, 2]))
39
+ (-1, 3)
40
+ """
41
+ lowest_value = values.min()
42
+ highest_value = values.max()
43
+ low_bound = int(lowest_value)
44
+ high_bound = int(highest_value)
45
+
46
+ return low_bound, high_bound
47
+
48
+
49
+ def find_result_bounds(left: tuple[int, int], right: tuple[int, int], function: numpy.ufunc) -> tuple[int, int]:
50
+ """
51
+ Return bounds that every result of an integer function stays within.
52
+
53
+ .. versionadded:: 0.1.0
54
+
55
+ Parameters
56
+ ----------
57
+ left
58
+ The bounds of the left operand.
59
+ right
60
+ The bounds of the right operand. No divisor is 0 and no power is negative.
61
+ function
62
+ ``numpy.add``, ``numpy.subtract``, ``numpy.multiply``, ``numpy.floor_divide`` or ``numpy.power``.
63
+
64
+ Returns
65
+ -------
66
+ tuple[int, int]
67
+ The low and the high bounds.
68
+
69
+ Examples
70
+ --------
71
+ >>> import numpy
72
+ >>> from numdaplot.arrays.operations.integer_bounds import find_result_bounds
73
+ >>> find_result_bounds((-2, 3), (4, 5), numpy.multiply)
74
+ (-10, 15)
75
+ """
76
+ left_low, left_high = left
77
+ right_low, right_high = right
78
+ if function == numpy.add:
79
+ sum_bounds = (left_low + right_low, left_high + right_high)
80
+ return sum_bounds
81
+
82
+ if function == numpy.subtract:
83
+ difference_bounds = (left_low - right_high, left_high - right_low)
84
+ return difference_bounds
85
+
86
+ if function == numpy.multiply:
87
+ products = [left_low * right_low, left_low * right_high, left_high * right_low, left_high * right_high]
88
+ lowest_product = min(products)
89
+ highest_product = max(products)
90
+ return lowest_product, highest_product
91
+
92
+ left_magnitude = max(abs(left_low), abs(left_high))
93
+ if function == numpy.floor_divide:
94
+ has_negative = left_low < 0 or right_low < 0
95
+ lowest_quotient = -left_magnitude if has_negative else 0
96
+ return lowest_quotient, left_magnitude
97
+
98
+ highest_power = find_power_bound(left_magnitude, right_high)
99
+ lowest_power = -highest_power if left_low < 0 else 0
100
+
101
+ return lowest_power, highest_power
102
+
103
+
104
+ def find_power_bound(magnitude: int, power: int) -> int:
105
+ """
106
+ Return a bound of the absolute value of integers raised to a power.
107
+
108
+ .. versionadded:: 0.1.0
109
+
110
+ Parameters
111
+ ----------
112
+ magnitude
113
+ The highest absolute value of the integers.
114
+ power
115
+ The highest power, 0 or more.
116
+
117
+ Returns
118
+ -------
119
+ int
120
+ The bound, or a number beyond every integer type when the exact bound would be huge.
121
+
122
+ Examples
123
+ --------
124
+ >>> from numdaplot.arrays.operations.integer_bounds import find_power_bound
125
+ >>> find_power_bound(2, 10)
126
+ 1024
127
+ >>> find_power_bound(3, 10**18) > 2**64
128
+ True
129
+ """
130
+ if magnitude <= 1:
131
+ return 1
132
+
133
+ magnitude_bits = math.log2(magnitude)
134
+ power_bits = power * magnitude_bits
135
+ if power_bits > LARGEST_COMPUTED_BITS:
136
+ return BEYOND_EVERY_INTEGER
137
+
138
+ power_bound = magnitude**power
139
+
140
+ return power_bound
141
+
142
+
143
+ def find_sum_bounds(values: NDArray[Any], axis: int | None) -> tuple[int, int]:
144
+ """
145
+ Return bounds that every sum of integers or booleans stays within.
146
+
147
+ .. versionadded:: 0.1.0
148
+
149
+ Parameters
150
+ ----------
151
+ values
152
+ At least one integer or boolean.
153
+ axis
154
+ The numpy axis reduced, or ``None`` for the whole Array.
155
+
156
+ Returns
157
+ -------
158
+ tuple[int, int]
159
+ The low and the high bounds.
160
+
161
+ Examples
162
+ --------
163
+ >>> import numpy
164
+ >>> from numdaplot.arrays.operations.integer_bounds import find_sum_bounds
165
+ >>> find_sum_bounds(numpy.array([[1, 2], [-3, 4]]), None)
166
+ (-12, 16)
167
+ >>> find_sum_bounds(numpy.array([[1, 2], [-3, 4]]), 1)
168
+ (-6, 8)
169
+ """
170
+ value_count = values.size if axis is None else values.shape[axis]
171
+ low_value, high_value = find_value_bounds(values)
172
+ low_bound = min(low_value, 0) * value_count
173
+ high_bound = max(high_value, 0) * value_count
174
+
175
+ return low_bound, high_bound
@@ -0,0 +1,397 @@
1
+ """
2
+ Refusal of integer calculations whose result numpy would silently write as a wrong number.
3
+
4
+ .. versionadded:: 0.1.0
5
+ """
6
+
7
+ from typing import Any
8
+
9
+ import numpy
10
+ from numpy.typing import NDArray
11
+
12
+ from numdaplot.arrays.operations.integer_bounds import find_result_bounds, find_sum_bounds, find_value_bounds
13
+ from numdaplot.arrays.operations.operand import Operand
14
+ from numdaplot.data_types.numpy_mapping import from_numpy_dtype
15
+ from numdaplot.errors.integer_overflow_error import IntegerOverflowError
16
+ from numdaplot.errors.out_of_domain_error import OutOfDomainError
17
+
18
+ SIGNED_KIND = "i"
19
+ UNSIGNED_KIND = "u"
20
+ INTEGER_KINDS = frozenset({SIGNED_KIND, UNSIGNED_KIND})
21
+ INTEGER_OR_BOOL_KINDS = frozenset({SIGNED_KIND, UNSIGNED_KIND, "b"})
22
+ POWER_NAME = "Power"
23
+ ZERO_DIVISION_NAMES = dict[numpy.ufunc, str](
24
+ {
25
+ numpy.floor_divide: "Floor division",
26
+ numpy.remainder: "Remainder",
27
+ }
28
+ )
29
+ OVERFLOWING_FUNCTIONS = frozenset({numpy.add, numpy.subtract, numpy.multiply, numpy.power, numpy.floor_divide})
30
+ PYTHON_OBJECT_DTYPE = numpy.dtype(object)
31
+ ESTIMATE_DTYPE = numpy.dtype(numpy.float64)
32
+ IGNORE_MODE = "ignore"
33
+ # A decimal estimate below half the limit cannot hide a result above it, and one above twice the limit cannot hide a
34
+ # result below it. Exact integers are computed only between both, which also avoids computing huge powers.
35
+ SAFE_ESTIMATE_RATIO = 0.5
36
+ CERTAIN_ESTIMATE_RATIO = 2
37
+
38
+
39
+ def require_defined_integers(left: Operand, right: Operand, function: numpy.ufunc) -> None:
40
+ """
41
+ Check that an operation between integers has a result an integer can hold.
42
+
43
+ .. versionadded:: 0.1.0
44
+
45
+ Parameters
46
+ ----------
47
+ left
48
+ The values of an Array, or a single value.
49
+ right
50
+ The values of an Array, or a single value.
51
+ function
52
+ The numpy function about to be applied.
53
+
54
+ Raises
55
+ ------
56
+ OutOfDomainError
57
+ When integers are divided by 0 with ``//`` or ``%``, or raised to a negative power.
58
+
59
+ Examples
60
+ --------
61
+ >>> import numpy
62
+ >>> import numdaplot as ndp
63
+ >>> from numdaplot.arrays.operations.integer_rules import require_defined_integers
64
+ >>> try:
65
+ ... require_defined_integers(numpy.array([1, 2]), 0, numpy.floor_divide)
66
+ ... except ndp.OutOfDomainError as error:
67
+ ... print(error)
68
+ Floor division is not defined for 0 between integers. Convert the values to FLOAT64 first.
69
+ """
70
+ left_values = numpy.asarray(left)
71
+ right_values = numpy.asarray(right)
72
+ has_integers = left_values.dtype.kind in INTEGER_OR_BOOL_KINDS and right_values.dtype.kind in INTEGER_OR_BOOL_KINDS
73
+ if not has_integers:
74
+ return
75
+
76
+ if function in ZERO_DIVISION_NAMES:
77
+ zeros = right_values == 0
78
+ has_zero = bool(zeros.any())
79
+ if has_zero:
80
+ raise OutOfDomainError(ZERO_DIVISION_NAMES[function], 0, True)
81
+
82
+ if function == numpy.power:
83
+ negatives = right_values < 0
84
+ has_negative = bool(negatives.any())
85
+ if has_negative:
86
+ negative_values = right_values[negatives]
87
+ first_negative = negative_values[0].item()
88
+ raise OutOfDomainError(POWER_NAME, first_negative, True)
89
+
90
+
91
+ def require_combination_fits(operands: list[Operand], function: numpy.ufunc, result: NDArray[Any], symbol: str) -> None:
92
+ """
93
+ Check that the integers of a result were not wrapped around by numpy.
94
+
95
+ .. versionadded:: 0.1.0
96
+
97
+ Parameters
98
+ ----------
99
+ operands
100
+ The left and the right operands, each the values of an Array or a single value.
101
+ function
102
+ The numpy function that was applied.
103
+ result
104
+ Its result.
105
+ symbol
106
+ The operator shown in the error message.
107
+
108
+ Raises
109
+ ------
110
+ IntegerOverflowError
111
+ When a result does not fit the integer type of ``result``.
112
+
113
+ Examples
114
+ --------
115
+ >>> import numpy
116
+ >>> from numdaplot.arrays.operations.integer_rules import require_combination_fits
117
+ >>> require_combination_fits([numpy.array([1]), 2], numpy.add, numpy.array([3]), "+")
118
+ """
119
+ if result.dtype.kind not in INTEGER_KINDS:
120
+ return
121
+
122
+ if function not in OVERFLOWING_FUNCTIONS:
123
+ return
124
+
125
+ left_operand, right_operand = operands
126
+ left_array = numpy.asarray(left_operand)
127
+ right_array = numpy.asarray(right_operand)
128
+ if left_array.size == 0 or right_array.size == 0:
129
+ return
130
+
131
+ left_bounds = find_value_bounds(left_array)
132
+ right_bounds = find_value_bounds(right_array)
133
+ result_bounds = find_result_bounds(left_bounds, right_bounds, function)
134
+ bounds_fit = do_bounds_fit(result_bounds, result)
135
+ if bounds_fit:
136
+ return
137
+
138
+ left_values, right_values = numpy.broadcast_arrays(left_array, right_array)
139
+ left_estimates = left_values.astype(ESTIMATE_DTYPE)
140
+ right_estimates = right_values.astype(ESTIMATE_DTYPE)
141
+ with numpy.errstate(all=IGNORE_MODE):
142
+ estimates = function(left_estimates, right_estimates)
143
+
144
+ doubtful = find_doubtful_estimates(estimates, result, symbol)
145
+ has_doubt = bool(doubtful.any())
146
+ if not has_doubt:
147
+ return
148
+
149
+ exact_left = left_values[doubtful].astype(PYTHON_OBJECT_DTYPE)
150
+ exact_right = right_values[doubtful].astype(PYTHON_OBJECT_DTYPE)
151
+ exact_values = function(exact_left, exact_right)
152
+ require_exact_values_fit(exact_values, result, symbol)
153
+
154
+
155
+ def require_sum_fits(values: NDArray[Any], axis: int | None, result: NDArray[Any], statistic_name: str) -> None:
156
+ """
157
+ Check that the integers of a sum were not wrapped around by numpy.
158
+
159
+ .. versionadded:: 0.1.0
160
+
161
+ Parameters
162
+ ----------
163
+ values
164
+ The summed values.
165
+ axis
166
+ The numpy axis reduced, or ``None`` for the whole Array.
167
+ result
168
+ The sum given by numpy.
169
+ statistic_name
170
+ Name of the statistic, shown in the error message.
171
+
172
+ Raises
173
+ ------
174
+ IntegerOverflowError
175
+ When a sum does not fit the integer type of ``result``.
176
+
177
+ Examples
178
+ --------
179
+ >>> import numpy
180
+ >>> import numdaplot as ndp
181
+ >>> from numdaplot.arrays.operations.integer_rules import require_sum_fits
182
+ >>> values = numpy.array([2**62, 2**62])
183
+ >>> try:
184
+ ... require_sum_fits(values, None, numpy.array([0]), "Sum")
185
+ ... except ndp.IntegerOverflowError as error:
186
+ ... print(error)
187
+ The operation Sum gives values too large for INT64. Convert the values to FLOAT64 first.
188
+ """
189
+ if result.dtype.kind not in INTEGER_KINDS:
190
+ return
191
+
192
+ if values.size == 0:
193
+ return
194
+
195
+ sum_bounds = find_sum_bounds(values, axis)
196
+ bounds_fit = do_bounds_fit(sum_bounds, result)
197
+ if bounds_fit:
198
+ return
199
+
200
+ decimal_values = values.astype(ESTIMATE_DTYPE)
201
+ estimates = numpy.sum(decimal_values, axis=axis)
202
+ estimate_values = numpy.asarray(estimates)
203
+ doubtful = find_doubtful_estimates(estimate_values, result, statistic_name)
204
+ has_doubt = bool(doubtful.any())
205
+ if not has_doubt:
206
+ return
207
+
208
+ exact_integers = values.astype(PYTHON_OBJECT_DTYPE)
209
+ exact_values = numpy.sum(exact_integers, axis=axis)
210
+ exact_array = numpy.asarray(exact_values, dtype=PYTHON_OBJECT_DTYPE)
211
+ require_exact_values_fit(exact_array, result, statistic_name)
212
+
213
+
214
+ def do_bounds_fit(bounds: tuple[int, int], result: NDArray[Any]) -> bool:
215
+ """
216
+ Return whether bounds of a result stay within the limits of its integer type.
217
+
218
+ .. versionadded:: 0.1.0
219
+
220
+ Parameters
221
+ ----------
222
+ bounds
223
+ The low and the high bounds of the result.
224
+ result
225
+ The result computed with integers, giving the integer type.
226
+
227
+ Returns
228
+ -------
229
+ bool
230
+ True when no value can have been wrapped around.
231
+
232
+ Examples
233
+ --------
234
+ >>> import numpy
235
+ >>> from numdaplot.arrays.operations.integer_rules import do_bounds_fit
236
+ >>> do_bounds_fit((0, 127), numpy.array([0], dtype="int8"))
237
+ True
238
+ >>> do_bounds_fit((0, 128), numpy.array([0], dtype="int8"))
239
+ False
240
+ """
241
+ limits = numpy.iinfo(result.dtype)
242
+ low_bound, high_bound = bounds
243
+ bounds_fit = limits.min <= low_bound and high_bound <= limits.max
244
+
245
+ return bounds_fit
246
+
247
+
248
+ def require_absolute_fits(values: NDArray[Any], operation_name: str) -> None:
249
+ """
250
+ Check that signed integers have an absolute value of their type: the lowest integer has none.
251
+
252
+ .. versionadded:: 0.1.0
253
+
254
+ Parameters
255
+ ----------
256
+ values
257
+ The values of a number Array.
258
+ operation_name
259
+ The operator or the function, shown in the error message.
260
+
261
+ Raises
262
+ ------
263
+ IntegerOverflowError
264
+ When a value is the lowest integer of its type.
265
+
266
+ Examples
267
+ --------
268
+ >>> import numpy
269
+ >>> from numdaplot.arrays.operations.integer_rules import require_absolute_fits
270
+ >>> require_absolute_fits(numpy.array([-1, 2]), "Absolute")
271
+ """
272
+ if values.dtype.kind != SIGNED_KIND:
273
+ return
274
+
275
+ limits = numpy.iinfo(values.dtype)
276
+ is_lowest = values == limits.min
277
+ has_lowest = bool(is_lowest.any())
278
+ if has_lowest:
279
+ values_type = from_numpy_dtype(values.dtype)
280
+ raise IntegerOverflowError(operation_name, values_type.name)
281
+
282
+
283
+ def require_opposite_fits(values: NDArray[Any], operation_name: str) -> None:
284
+ """
285
+ Check that integers have an opposite of their type: unsigned integers only have the opposite of 0.
286
+
287
+ .. versionadded:: 0.1.0
288
+
289
+ Parameters
290
+ ----------
291
+ values
292
+ The values of a number Array.
293
+ operation_name
294
+ The operator, shown in the error message.
295
+
296
+ Raises
297
+ ------
298
+ IntegerOverflowError
299
+ When a value has no opposite in its type.
300
+
301
+ Examples
302
+ --------
303
+ >>> import numpy
304
+ >>> from numdaplot.arrays.operations.integer_rules import require_opposite_fits
305
+ >>> require_opposite_fits(numpy.array([0], dtype="uint8"), "-")
306
+ """
307
+ require_absolute_fits(values, operation_name)
308
+ if values.dtype.kind != UNSIGNED_KIND:
309
+ return
310
+
311
+ has_value_above_zero = bool(values.any())
312
+ if has_value_above_zero:
313
+ values_type = from_numpy_dtype(values.dtype)
314
+ raise IntegerOverflowError(operation_name, values_type.name)
315
+
316
+
317
+ def find_doubtful_estimates(estimates: NDArray[Any], result: NDArray[Any], operation_name: str) -> NDArray[numpy.bool_]:
318
+ """
319
+ Return which decimal estimates of integers need an exact calculation.
320
+
321
+ .. versionadded:: 0.1.0
322
+
323
+ Parameters
324
+ ----------
325
+ estimates
326
+ The result computed with decimals.
327
+ result
328
+ The result computed with integers, giving the integer type.
329
+ operation_name
330
+ The operator or the statistic, shown in the error message.
331
+
332
+ Returns
333
+ -------
334
+ NDArray[numpy.bool_]
335
+ True at each estimate too close to the limits of the type to conclude.
336
+
337
+ Raises
338
+ ------
339
+ IntegerOverflowError
340
+ When an estimate is far above the limits of the type.
341
+
342
+ Examples
343
+ --------
344
+ >>> import numpy
345
+ >>> from numdaplot.arrays.operations.integer_rules import find_doubtful_estimates
346
+ >>> find_doubtful_estimates(numpy.array([1.0, 100.0]), numpy.array([1, 100], dtype="int8"), "+")
347
+ array([False, True])
348
+ """
349
+ limits = numpy.iinfo(result.dtype)
350
+ magnitudes = numpy.abs(estimates)
351
+ is_certain = magnitudes >= limits.max * CERTAIN_ESTIMATE_RATIO
352
+ has_certain_overflow = bool(numpy.any(is_certain))
353
+ if has_certain_overflow:
354
+ result_type = from_numpy_dtype(result.dtype)
355
+ raise IntegerOverflowError(operation_name, result_type.name)
356
+
357
+ is_near_limit = magnitudes >= limits.max * SAFE_ESTIMATE_RATIO
358
+ is_below_lowest = estimates < limits.min
359
+ doubtful = is_near_limit | is_below_lowest
360
+
361
+ return doubtful
362
+
363
+
364
+ def require_exact_values_fit(exact_values: NDArray[Any], result: NDArray[Any], operation_name: str) -> None:
365
+ """
366
+ Check that exact Python integers fit an integer type.
367
+
368
+ .. versionadded:: 0.1.0
369
+
370
+ Parameters
371
+ ----------
372
+ exact_values
373
+ Python integers, in a numpy array of objects.
374
+ result
375
+ The result computed with integers, giving the integer type.
376
+ operation_name
377
+ The operator or the statistic, shown in the error message.
378
+
379
+ Raises
380
+ ------
381
+ IntegerOverflowError
382
+ When a value is outside the limits of the type.
383
+
384
+ Examples
385
+ --------
386
+ >>> import numpy
387
+ >>> from numdaplot.arrays.operations.integer_rules import require_exact_values_fit
388
+ >>> require_exact_values_fit(numpy.array([100], dtype=object), numpy.array([100], dtype="int8"), "+")
389
+ """
390
+ limits = numpy.iinfo(result.dtype)
391
+ is_above = exact_values > limits.max
392
+ is_below = exact_values < limits.min
393
+ is_outside = is_above | is_below
394
+ has_outside_value = bool(numpy.any(is_outside))
395
+ if has_outside_value:
396
+ result_type = from_numpy_dtype(result.dtype)
397
+ raise IntegerOverflowError(operation_name, result_type.name)
@@ -0,0 +1,139 @@
1
+ """
2
+ Values an Array can be combined with.
3
+
4
+ .. versionadded:: 0.1.0
5
+ """
6
+
7
+ from datetime import date, time, timedelta
8
+ from typing import Any
9
+
10
+ import numpy
11
+ from numpy.typing import NDArray
12
+
13
+ from numdaplot.data_types.numpy_mapping import from_numpy_dtype
14
+ from numdaplot.data_types.time_of_day import to_time_since_midnight
15
+ from numdaplot.data_types.type import Type
16
+ from numdaplot.data_types.value_type import find_value_type
17
+ from numdaplot.rules.rule_values import ScalarValue
18
+
19
+ MICROSECONDS_IN_COUNT = 2**63 - 1
20
+ LONGEST_MICROSECOND_DURATION = timedelta(microseconds=MICROSECONDS_IN_COUNT)
21
+ ONE_SECOND = timedelta(seconds=1)
22
+ SECOND_CODE = "s"
23
+ TIME_CODE = "us"
24
+
25
+ type Operand = NDArray[Any] | ScalarValue
26
+ """The values of an Array, or a single value, on one side of an operation.
27
+
28
+ .. versionadded:: 0.1.0
29
+ """
30
+
31
+
32
+ def find_operand_type(operand: Operand) -> Type:
33
+ """
34
+ Return the numdaplot type of the values on one side of an operation.
35
+
36
+ .. versionadded:: 0.1.0
37
+
38
+ Parameters
39
+ ----------
40
+ operand
41
+ The values of an Array, or a single value.
42
+
43
+ Returns
44
+ -------
45
+ Type
46
+ The type of the values.
47
+
48
+ Examples
49
+ --------
50
+ >>> import numpy
51
+ >>> from numdaplot.arrays.operations.operand import find_operand_type
52
+ >>> find_operand_type(numpy.array([1.5]))
53
+ <Type.FLOAT64: 10>
54
+ """
55
+ if isinstance(operand, numpy.ndarray):
56
+ array_type = from_numpy_dtype(operand.dtype)
57
+ return array_type
58
+
59
+ value_type = find_value_type(operand)
60
+
61
+ return value_type
62
+
63
+
64
+ def find_operand_type_names(operands: list[Operand]) -> list[str]:
65
+ """
66
+ Return the names of the numdaplot types of several operands, as shown in error messages.
67
+
68
+ .. versionadded:: 0.1.0
69
+
70
+ Parameters
71
+ ----------
72
+ operands
73
+ The values of Arrays, or single values.
74
+
75
+ Returns
76
+ -------
77
+ list[str]
78
+ The name of the type of each operand, in order.
79
+
80
+ Examples
81
+ --------
82
+ >>> import numpy
83
+ >>> from numdaplot.arrays.operations.operand import find_operand_type_names
84
+ >>> find_operand_type_names([numpy.array([1]), "euros"])
85
+ ['INT64', 'TEXT']
86
+ """
87
+ operand_types = [find_operand_type(operand) for operand in operands]
88
+ type_names = [operand_type.name for operand_type in operand_types]
89
+
90
+ return type_names
91
+
92
+
93
+ def convert_time_value(value: ScalarValue) -> Any:
94
+ """
95
+ Return a single value in the form numpy compares with Array values.
96
+
97
+ numpy compares a Python date with its own dates through Python objects, which fails on a missing date.
98
+
99
+ .. versionadded:: 0.1.0
100
+
101
+ Parameters
102
+ ----------
103
+ value
104
+ A single value.
105
+
106
+ Returns
107
+ -------
108
+ Any
109
+ A ``numpy.datetime64`` for a date or a datetime, a ``numpy.timedelta64`` for a duration, in seconds when
110
+ microseconds cannot count it, the time since midnight in microseconds for a time of day, the value itself
111
+ otherwise.
112
+
113
+ Examples
114
+ --------
115
+ >>> from datetime import date
116
+ >>> from numdaplot.arrays.operations.operand import convert_time_value
117
+ >>> convert_time_value(date(2026, 1, 31))
118
+ np.datetime64('2026-01-31')
119
+ """
120
+ if isinstance(value, date):
121
+ moment = numpy.datetime64(value)
122
+ return moment
123
+
124
+ if isinstance(value, time):
125
+ since_midnight = to_time_since_midnight(value)
126
+ time_of_day = numpy.timedelta64(since_midnight, TIME_CODE)
127
+ return time_of_day
128
+
129
+ if isinstance(value, timedelta):
130
+ is_too_long_for_microseconds = abs(value) > LONGEST_MICROSECOND_DURATION
131
+ if is_too_long_for_microseconds:
132
+ whole_seconds = value // ONE_SECOND
133
+ second_duration = numpy.timedelta64(whole_seconds, SECOND_CODE)
134
+ return second_duration
135
+
136
+ duration = numpy.timedelta64(value)
137
+ return duration
138
+
139
+ return value