xmime.hpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431
  1. /***************************************************************************
  2. * Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
  3. * Copyright (c) QuantStack *
  4. * *
  5. * Distributed under the terms of the BSD 3-Clause License. *
  6. * *
  7. * The full license is in the file LICENSE, distributed with this software. *
  8. ****************************************************************************/
  9. #ifndef XTENSOR_MIME_HPP
  10. #define XTENSOR_MIME_HPP
  11. #include <cstddef>
  12. #include <sstream>
  13. #include <string>
  14. #include <vector>
  15. #include <nlohmann/json.hpp>
  16. #include "xio.hpp"
  17. namespace xt
  18. {
  19. template <class P, class T>
  20. void compute_0d_table(std::stringstream& out, P& /*printer*/, const T& expr)
  21. {
  22. out << "<table style='border-style:solid;border-width:1px;'><tbody>";
  23. out << "<tr><td style='font-family:monospace;'><pre>";
  24. out << expr();
  25. out << "</pre></td></tr>";
  26. out << "</tbody></table>";
  27. }
  28. template <class P>
  29. void compute_1d_row(std::stringstream& out, P& printer, const std::size_t& row_idx)
  30. {
  31. out << "<tr><td style='font-family:monospace;' title='" << row_idx << "'><pre>";
  32. printer.print_next(out);
  33. out << "</pre></td></tr>";
  34. }
  35. template <class P, class T>
  36. void compute_1d_table(std::stringstream& out, P& printer, const T& expr, const std::size_t& edgeitems)
  37. {
  38. const auto& dim = expr.shape()[0];
  39. out << "<table style='border-style:solid;border-width:1px;'><tbody>";
  40. if (edgeitems == 0 || 2 * edgeitems >= dim)
  41. {
  42. for (std::size_t row_idx = 0; row_idx < dim; ++row_idx)
  43. {
  44. compute_1d_row(out, printer, row_idx);
  45. }
  46. }
  47. else
  48. {
  49. for (std::size_t row_idx = 0; row_idx < edgeitems; ++row_idx)
  50. {
  51. compute_1d_row(out, printer, row_idx);
  52. }
  53. out << "<tr><td><center>\u22ee</center></td></tr>";
  54. for (std::size_t row_idx = dim - edgeitems; row_idx < dim; ++row_idx)
  55. {
  56. compute_1d_row(out, printer, row_idx);
  57. }
  58. }
  59. out << "</tbody></table>";
  60. }
  61. template <class P>
  62. void compute_2d_element(
  63. std::stringstream& out,
  64. P& printer,
  65. const std::string& idx_str,
  66. const std::size_t& row_idx,
  67. const std::size_t& column_idx
  68. )
  69. {
  70. out << "<td style='font-family:monospace;' title='(" << idx_str << row_idx << ", " << column_idx
  71. << ")'><pre>";
  72. printer.print_next(out);
  73. out << "</pre></td>";
  74. }
  75. template <class P, class T>
  76. void compute_2d_row(
  77. std::stringstream& out,
  78. P& printer,
  79. const T& expr,
  80. const std::size_t& edgeitems,
  81. const std::string& idx_str,
  82. const std::size_t& row_idx
  83. )
  84. {
  85. const auto& dim = expr.shape()[expr.dimension() - 1];
  86. out << "<tr>";
  87. if (edgeitems == 0 || 2 * edgeitems >= dim)
  88. {
  89. for (std::size_t column_idx = 0; column_idx < dim; ++column_idx)
  90. {
  91. compute_2d_element(out, printer, idx_str, row_idx, column_idx);
  92. }
  93. }
  94. else
  95. {
  96. for (std::size_t column_idx = 0; column_idx < edgeitems; ++column_idx)
  97. {
  98. compute_2d_element(out, printer, idx_str, row_idx, column_idx);
  99. }
  100. out << "<td><center>\u22ef</center></td>";
  101. for (std::size_t column_idx = dim - edgeitems; column_idx < dim; ++column_idx)
  102. {
  103. compute_2d_element(out, printer, idx_str, row_idx, column_idx);
  104. }
  105. }
  106. out << "</tr>";
  107. }
  108. template <class P, class T, class I>
  109. void compute_2d_table(
  110. std::stringstream& out,
  111. P& printer,
  112. const T& expr,
  113. const std::size_t& edgeitems,
  114. const std::vector<I>& idx
  115. )
  116. {
  117. const auto& dim = expr.shape()[expr.dimension() - 2];
  118. const auto& last_dim = expr.shape()[expr.dimension() - 1];
  119. std::string idx_str;
  120. std::for_each(
  121. idx.cbegin(),
  122. idx.cend(),
  123. [&idx_str](const auto& i)
  124. {
  125. idx_str += std::to_string(i) + ", ";
  126. }
  127. );
  128. std::size_t nb_ellipsis = 2 * edgeitems + 1;
  129. if (last_dim <= 2 * edgeitems + 1)
  130. {
  131. nb_ellipsis = last_dim;
  132. }
  133. out << "<table style='border-style:solid;border-width:1px;'><tbody>";
  134. if (edgeitems == 0 || 2 * edgeitems >= dim)
  135. {
  136. for (std::size_t row_idx = 0; row_idx < dim; ++row_idx)
  137. {
  138. compute_2d_row(out, printer, expr, edgeitems, idx_str, row_idx);
  139. }
  140. }
  141. else
  142. {
  143. for (std::size_t row_idx = 0; row_idx < edgeitems; ++row_idx)
  144. {
  145. compute_2d_row(out, printer, expr, edgeitems, idx_str, row_idx);
  146. }
  147. out << "<tr>";
  148. for (std::size_t column_idx = 0; column_idx < nb_ellipsis; ++column_idx)
  149. {
  150. if (column_idx == edgeitems && nb_ellipsis != last_dim)
  151. {
  152. out << "<td><center>\u22f1</center></td>";
  153. }
  154. else
  155. {
  156. out << "<td><center>\u22ee</center></td>";
  157. }
  158. }
  159. out << "</tr>";
  160. for (std::size_t row_idx = dim - edgeitems; row_idx < dim; ++row_idx)
  161. {
  162. compute_2d_row(out, printer, expr, edgeitems, idx_str, row_idx);
  163. }
  164. }
  165. out << "</tbody></table>";
  166. }
  167. template <class P, class T, class I>
  168. void compute_nd_row(
  169. std::stringstream& out,
  170. P& printer,
  171. const T& expr,
  172. const std::size_t& edgeitems,
  173. const std::vector<I>& idx
  174. )
  175. {
  176. out << "<tr><td>";
  177. compute_nd_table_impl(out, printer, expr, edgeitems, idx);
  178. out << "</td></tr>";
  179. }
  180. template <class P, class T, class I>
  181. void compute_nd_table_impl(
  182. std::stringstream& out,
  183. P& printer,
  184. const T& expr,
  185. const std::size_t& edgeitems,
  186. const std::vector<I>& idx
  187. )
  188. {
  189. const auto& displayed_dimension = idx.size();
  190. const auto& expr_dim = expr.dimension();
  191. const auto& dim = expr.shape()[displayed_dimension];
  192. if (expr_dim - displayed_dimension == 2)
  193. {
  194. return compute_2d_table(out, printer, expr, edgeitems, idx);
  195. }
  196. std::vector<I> idx2 = idx;
  197. idx2.resize(displayed_dimension + 1);
  198. out << "<table style='border-style:solid;border-width:1px;'>";
  199. if (edgeitems == 0 || 2 * edgeitems >= dim)
  200. {
  201. for (std::size_t i = 0; i < dim; ++i)
  202. {
  203. idx2[displayed_dimension] = i;
  204. compute_nd_row(out, printer, expr, edgeitems, idx2);
  205. }
  206. }
  207. else
  208. {
  209. for (std::size_t i = 0; i < edgeitems; ++i)
  210. {
  211. idx2[displayed_dimension] = i;
  212. compute_nd_row(out, printer, expr, edgeitems, idx2);
  213. }
  214. out << "<tr><td><center>\u22ef</center></td></tr>";
  215. for (std::size_t i = dim - edgeitems; i < dim; ++i)
  216. {
  217. idx2[displayed_dimension] = i;
  218. compute_nd_row(out, printer, expr, edgeitems, idx2);
  219. }
  220. }
  221. out << "</table>";
  222. }
  223. template <class P, class T>
  224. void compute_nd_table(std::stringstream& out, P& printer, const T& expr, const std::size_t& edgeitems)
  225. {
  226. if (expr.dimension() == 0)
  227. {
  228. compute_0d_table(out, printer, expr);
  229. }
  230. else if (expr.dimension() == 1)
  231. {
  232. compute_1d_table(out, printer, expr, edgeitems);
  233. }
  234. else
  235. {
  236. std::vector<std::size_t> empty_vector;
  237. compute_nd_table_impl(out, printer, expr, edgeitems, empty_vector);
  238. }
  239. }
  240. template <class E>
  241. nlohmann::json mime_bundle_repr_impl(const E& expr)
  242. {
  243. std::stringstream out;
  244. std::size_t edgeitems = 0;
  245. std::size_t size = compute_size(expr.shape());
  246. if (size > static_cast<std::size_t>(print_options::print_options().threshold))
  247. {
  248. edgeitems = static_cast<std::size_t>(print_options::print_options().edge_items);
  249. }
  250. if (print_options::print_options().precision != -1)
  251. {
  252. out.precision(print_options::print_options().precision);
  253. }
  254. detail::printer<E> printer(out.precision());
  255. xstrided_slice_vector slice_vector;
  256. detail::recurser_run(printer, expr, slice_vector, edgeitems);
  257. printer.init();
  258. compute_nd_table(out, printer, expr, edgeitems);
  259. auto bundle = nlohmann::json::object();
  260. bundle["text/html"] = out.str();
  261. return bundle;
  262. }
  263. template <class F, class CT>
  264. class xfunctor_view;
  265. template <class F, class CT>
  266. nlohmann::json mime_bundle_repr(const xfunctor_view<F, CT>& expr)
  267. {
  268. return mime_bundle_repr_impl(expr);
  269. }
  270. template <class F, class... CT>
  271. class xfunction;
  272. template <class F, class... CT>
  273. nlohmann::json mime_bundle_repr(const xfunction<F, CT...>& expr)
  274. {
  275. return mime_bundle_repr_impl(expr);
  276. }
  277. template <class EC, layout_type L, class SC, class Tag>
  278. class xarray_container;
  279. template <class EC, layout_type L, class SC, class Tag>
  280. nlohmann::json mime_bundle_repr(const xarray_container<EC, L, SC, Tag>& expr)
  281. {
  282. return mime_bundle_repr_impl(expr);
  283. }
  284. template <class EC, std::size_t N, layout_type L, class Tag>
  285. class xtensor_container;
  286. template <class EC, std::size_t N, layout_type L, class Tag>
  287. nlohmann::json mime_bundle_repr(const xtensor_container<EC, N, L, Tag>& expr)
  288. {
  289. return mime_bundle_repr_impl(expr);
  290. }
  291. template <class ET, class S, layout_type L, bool SH, class Tag>
  292. class xfixed_container;
  293. template <class ET, class S, layout_type L, bool SH, class Tag>
  294. nlohmann::json mime_bundle_repr(const xfixed_container<ET, S, L, SH, Tag>& expr)
  295. {
  296. return mime_bundle_repr_impl(expr);
  297. }
  298. template <class F, class CT, class X, class O>
  299. class xreducer;
  300. template <class F, class CT, class X, class O>
  301. nlohmann::json mime_bundle_repr(const xreducer<F, CT, X, O>& expr)
  302. {
  303. return mime_bundle_repr_impl(expr);
  304. }
  305. template <class VE, class FE>
  306. class xoptional_assembly;
  307. template <class VE, class FE>
  308. nlohmann::json mime_bundle_repr(const xoptional_assembly<VE, FE>& expr)
  309. {
  310. return mime_bundle_repr_impl(expr);
  311. }
  312. template <class VEC, class FEC>
  313. class xoptional_assembly_adaptor;
  314. template <class VEC, class FEC>
  315. nlohmann::json mime_bundle_repr(const xoptional_assembly_adaptor<VEC, FEC>& expr)
  316. {
  317. return mime_bundle_repr_impl(expr);
  318. }
  319. template <class CT>
  320. class xscalar;
  321. template <class CT>
  322. nlohmann::json mime_bundle_repr(const xscalar<CT>& expr)
  323. {
  324. return mime_bundle_repr_impl(expr);
  325. }
  326. template <class CT, class X>
  327. class xbroadcast;
  328. template <class CT, class X>
  329. nlohmann::json mime_bundle_repr(const xbroadcast<CT, X>& expr)
  330. {
  331. return mime_bundle_repr_impl(expr);
  332. }
  333. template <class F, class R, class S>
  334. class xgenerator;
  335. template <class F, class R, class S>
  336. nlohmann::json mime_bundle_repr(const xgenerator<F, R, S>& expr)
  337. {
  338. return mime_bundle_repr_impl(expr);
  339. }
  340. template <class CT, class... S>
  341. class xview;
  342. template <class CT, class... S>
  343. nlohmann::json mime_bundle_repr(const xview<CT, S...>& expr)
  344. {
  345. return mime_bundle_repr_impl(expr);
  346. }
  347. template <class CT, class S, layout_type L, class FST>
  348. class xstrided_view;
  349. template <class CT, class S, layout_type L, class FST>
  350. nlohmann::json mime_bundle_repr(const xstrided_view<CT, S, L, FST>& expr)
  351. {
  352. return mime_bundle_repr_impl(expr);
  353. }
  354. template <class CTD, class CTM>
  355. class xmasked_view;
  356. template <class CTD, class CTM>
  357. nlohmann::json mime_bundle_repr(const xmasked_view<CTD, CTM>& expr)
  358. {
  359. return mime_bundle_repr_impl(expr);
  360. }
  361. template <class T, class B>
  362. class xmasked_value;
  363. template <class T, class B>
  364. nlohmann::json mime_bundle_repr(const xmasked_value<T, B>& v)
  365. {
  366. auto bundle = nlohmann::json::object();
  367. std::stringstream tmp;
  368. tmp << v;
  369. bundle["text/plain"] = tmp.str();
  370. return bundle;
  371. }
  372. }
  373. #endif