File: common.h

package info (click to toggle)
gemmi 0.7.4%2Bds-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 6,644 kB
  • sloc: cpp: 64,445; python: 5,425; ansic: 4,545; sh: 374; makefile: 112; javascript: 86; f90: 42
file content (143 lines) | stat: -rw-r--r-- 4,603 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143

#pragma once

#if defined(__clang__)
  #pragma clang diagnostic push
#elif defined(__GNUC__)
  #pragma GCC diagnostic push
  #pragma GCC diagnostic ignored "-Wpedantic"
#endif

#include <nanobind/nanobind.h>  // IWYU pragma: export
#include <gemmi/logger.hpp>     // for Logger

#if defined(__clang__)
  #pragma clang diagnostic pop
#elif defined(__GNUC__)
  #pragma GCC diagnostic pop
#endif

#if NB_VERSION_MAJOR < 2 || (NB_VERSION_MAJOR == 2 && NB_VERSION_MINOR < 2)
  #error Required nanobind version >= 2.2
#endif

namespace nb = nanobind;
constexpr auto rv_ri = nb::rv_policy::reference_internal;

void add_elem(nb::module_& m); // elem.cpp
void add_xds(nb::module_& m); // elem.cpp
void add_symmetry(nb::module_& m); // sym.cpp
void add_ccp4(nb::module_& m); // ccp4.cpp
void add_grid(nb::module_& m); // grid.cpp
void add_recgrid(nb::module_& m); // recgrid.cpp
void add_unitcell(nb::module_& m); // unitcell.cpp
void add_hkl(nb::module_& m); // hkl.cpp
void add_meta(nb::module_& m); // meta.cpp
void add_mol(nb::module_& m); // mol.cpp
void add_mtz(nb::module_& m); // mtz.cpp
void add_cif(nb::module_& cif); // cif.cpp
void add_cif_read(nb::module_& cif); // read.cpp
void add_read_structure(nb::module_& m); // read.cpp
void add_small(nb::module_& m); // read.cpp
void add_chemcomp(nb::module_& m); // chemcomp.cpp
void add_monlib(nb::module_& m); // monlib.cpp
void add_topo(nb::module_& m); // topo.cpp
void add_alignment(nb::module_& m); // align.cpp
void add_scaling(nb::module_& m); // scaling.cpp
void add_search(nb::module_& m); // search.cpp
void add_sf(nb::module_& m); // sf.cpp

// defined in write.cpp
namespace gemmi {
  struct Structure;
  namespace cif { struct Document; }
}

void add_write(nb::module_& m, nb::class_<gemmi::Structure>& structure);
// defined in align.cpp
void add_assign_label_seq_id(nb::class_<gemmi::Structure>& structure);

// convert pythonic index to C++ index
inline int c_index(int index, size_t size) {
  if (index < 0)
    index += (int) size;
  if ((size_t) index >= size)
    throw nb::index_error();
  return index;
}

template<typename T> int normalize_index(int index, const T& container) {
  return c_index(index, container.size());
}

// specialized for cif::Table in cif.cpp
template<typename Vec>
void delitem_at_index(Vec& items, size_t idx) {
  items.erase(items.begin() + idx);
}

// specialized for cif::Table in cif.cpp
template<typename Vec>
void delitem_range(Vec& items, size_t start, size_t end) {
  items.erase(items.begin() + start, items.begin() + end);
}

template<typename Items>
void delitem_slice(Items& items, const nb::slice& slice) {
  auto [start, stop, step, length] = slice.compute(items.size());
  if (step == 1) {
    delitem_range(items, start, start + length);
  } else {
    for (size_t i = 0; i < length; ++i)
      delitem_at_index(items, start + (step > 0 ? length - 1 - i : i) * step);
  }
}

template<typename Items>
nb::list getitem_slice(Items& items, const nb::slice& slice) {
  auto [start, stop, step, length] = slice.compute(items.size());
  nb::list l;
  for (size_t i = 0; i < length; ++i)
    l.append(nb::cast(&items[start + i * step]));
  return l;
}

// for numpy __array__ method
inline nb::object handle_numpy_array_args(const nb::object& o, nb::handle dtype, nb::handle copy) {
  if (dtype.is_none() || dtype.is(o.attr("dtype"))) {
    if (copy.ptr() != Py_True)
      return o;
    dtype = o.attr("dtype");
  }
  if (copy.ptr() == Py_False)  // astype() would copy even with copy=False
    throw nb::value_error("Unable to avoid copy while creating an array as requested.");
  return o.attr("astype")(dtype);
}

namespace nanobind { namespace detail {
template <> struct type_caster<gemmi::Logger> {
  NB_TYPE_CASTER(gemmi::Logger, const_name("object"))
  bool from_python(handle src, uint8_t, cleanup_list *) noexcept {
    value = {};
    if (PyTuple_Check(src.ptr()) && PyTuple_Size(src.ptr()) == 2) {
      value.threshold = (int) PyLong_AsLong(PyTuple_GetItem(src.ptr(), 1));
      if (value.threshold == -1 && PyErr_Occurred())
        return false;
      src = PyTuple_GetItem(src.ptr(), 0);
    }
    if (src.is_none()) {
      // nothing
    } else if (nb::hasattr(src, "write") && nb::hasattr(src, "flush")) {
      value.callback = {[obj=nb::borrow(src)](const std::string& s) {
        obj.attr("write")(s + "\n");
        obj.attr("flush")();
      }};
    } else if (PyCallable_Check(src.ptr())) {
      value.callback = {[obj=nb::borrow(src)](const std::string& s) { obj(s); }};
    } else {
      return false;
    }
    return true;
  }
};
}} // namespace nanobind::detail