LCOV - code coverage report
Current view: top level - python - variable.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 44 46 95.7 %
Date: 2024-11-17 01:47:58 Functions: 10 16 62.5 %

          Line data    Source code
       1             : // SPDX-License-Identifier: BSD-3-Clause
       2             : // Copyright (c) 2023 Scipp contributors (https://github.com/scipp)
       3             : /// @file
       4             : /// @author Simon Heybrock
       5             : 
       6             : #include "scipp/units/unit.h"
       7             : 
       8             : #include "scipp/core/spatial_transforms.h"
       9             : #include "scipp/core/time_point.h"
      10             : 
      11             : #include "scipp/variable/operations.h"
      12             : #include "scipp/variable/structures.h"
      13             : #include "scipp/variable/util.h"
      14             : #include "scipp/variable/variable.h"
      15             : #include "scipp/variable/variable_factory.h"
      16             : 
      17             : #include "scipp/dataset/dataset.h"
      18             : 
      19             : #include "bind_data_access.h"
      20             : #include "bind_operators.h"
      21             : #include "bind_slice_methods.h"
      22             : #include "dim.h"
      23             : #include "pybind11.h"
      24             : #include "rename.h"
      25             : 
      26             : using namespace scipp;
      27             : using namespace scipp::variable;
      28             : 
      29             : namespace py = pybind11;
      30             : 
      31             : template <class T> struct GetElements {
      32          42 :   static Variable apply(Variable &var, const std::string &key) {
      33          42 :     return var.elements<T>(key);
      34             :   }
      35             : };
      36             : 
      37             : template <class T> struct SetElements {
      38          17 :   static void apply(Variable &var, const std::string &key,
      39             :                     const Variable &elems) {
      40          17 :     copy(elems, var.elements<T>(key));
      41          16 :   }
      42             : };
      43             : 
      44           3 : template <class T> void bind_alignment_functions(py::class_<T> &variable) {
      45             :   // We use a separate setter instead of making the 'aligned' property writable
      46             :   // in order to reduce the chance of accidentally setting the flag on
      47             :   // temporary variables.
      48           3 :   variable.def_property_readonly(
      49        1418 :       "aligned", [](const Variable &self) { return self.is_aligned(); },
      50             :       R"(Alignment flag for coordinates.
      51             : 
      52             : Indicates whether a coordinate is aligned.
      53             : Aligned coordinates must match between the operands of binary operations while
      54             : unaligned coordinates are dropped on mismatch.
      55             : 
      56             : This flag is only meaningful when the variable is contained in a ``coords``
      57             : ``dict``.
      58             : 
      59             : It cannot be set on a variable directly;
      60             : instead, use :meth:`sc.Coords.set_aligned`.
      61             : 
      62             : For *binned* coordinates of a binned data array ``da``,
      63             : ``da.bins.coords[name].aligned`` should always be ``True``.
      64             : The alignment w.r.t. the events can be queried via
      65             : ``da.bins.coords[name].bins.aligned`` and set via
      66             : ``da.bins.coords.set_aligned(name, aligned)``.
      67             : )");
      68           3 : }
      69             : 
      70             : void bind_init(py::class_<Variable> &cls);
      71             : 
      72           3 : void init_variable(py::module &m) {
      73             :   // Needed to let numpy arrays keep alive the scipp buffers.
      74             :   // VariableConcept must ALWAYS be passed to Python by its handle.
      75             :   py::class_<VariableConcept, VariableConceptHandle> variable_concept(
      76           3 :       m, "_VariableConcept");
      77             : 
      78           0 :   py::class_<Variable> variable(m, "Variable", py::dynamic_attr(),
      79             :                                 R"(
      80             : Array of values with dimension labels and a unit, optionally including an array
      81           3 : of variances.)");
      82             : 
      83           3 :   bind_init(variable);
      84           3 :   variable.def("_rename_dims", &rename_dims<Variable>)
      85           3 :       .def_property_readonly("dtype", &Variable::dtype);
      86             : 
      87           3 :   bind_common_operators(variable);
      88             : 
      89           3 :   bind_astype(variable);
      90             : 
      91           3 :   bind_slice_methods(variable);
      92             : 
      93           3 :   bind_comparison<Variable>(variable);
      94           3 :   bind_comparison_scalars(variable);
      95             : 
      96           3 :   bind_in_place_binary<Variable>(variable);
      97           3 :   bind_in_place_binary_scalars(variable);
      98             : 
      99           3 :   bind_binary<Variable>(variable);
     100           3 :   bind_binary<DataArray>(variable);
     101           3 :   bind_binary_scalars(variable);
     102           3 :   bind_reverse_binary_scalars(variable);
     103             : 
     104           3 :   bind_unary(variable);
     105             : 
     106           3 :   bind_boolean_unary(variable);
     107           3 :   bind_logical<Variable>(variable);
     108             : 
     109           3 :   bind_data_properties(variable);
     110           3 :   bind_alignment_functions(variable);
     111             : 
     112           3 :   m.def(
     113             :       "islinspace",
     114          91 :       [](const Variable &x,
     115             :          const std::optional<std::string> &dim = std::nullopt) {
     116         151 :         return scipp::variable::islinspace(x, dim.has_value() ? Dim{*dim}
     117         151 :                                                               : x.dim());
     118             :       },
     119           6 :       py::arg("x"), py::arg("dim") = py::none(),
     120           0 :       py::call_guard<py::gil_scoped_release>());
     121             : 
     122             :   using structured_t =
     123             :       std::tuple<Eigen::Vector3d, Eigen::Matrix3d, Eigen::Affine3d,
     124             :                  scipp::core::Quaternion, scipp::core::Translation>;
     125           3 :   m.def("_element_keys", element_keys);
     126           3 :   m.def("_get_elements", [](Variable &self, const std::string &key) {
     127             :     return core::callDType<GetElements>(
     128          84 :         structured_t{}, variableFactory().elem_dtype(self), self, key);
     129             :   });
     130           3 :   m.def("_set_elements", [](Variable &self, const std::string &key,
     131             :                             const Variable &elems) {
     132          17 :     core::callDType<SetElements>(
     133          17 :         structured_t{}, variableFactory().elem_dtype(self), self, key, elems);
     134          16 :   });
     135           3 : }

Generated by: LCOV version 1.14