| 1236 | } |
| 1237 | |
| 1238 | static int SmithWaterman_init(SmithWaterman *self, PyObject *args, PyObject *kwargs) { |
| 1239 | PyObject *substitution_matrix_obj = NULL; |
| 1240 | sz_error_cost_t open = -1, extend = -1; |
| 1241 | PyObject *capabilities_tuple = NULL; |
| 1242 | sz_capability_t capabilities = default_hardware_capabilities; |
| 1243 | |
| 1244 | // Parse arguments: substitution_matrix, open, extend, capabilities |
| 1245 | static char *kwlist[] = {"substitution_matrix", "open", "extend", "capabilities", NULL}; |
| 1246 | if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iiO", kwlist, &substitution_matrix_obj, &open, &extend, |
| 1247 | &capabilities_tuple)) |
| 1248 | return -1; |
| 1249 | |
| 1250 | // Validate substitution matrix (should be a 256x256 numpy array) |
| 1251 | if (!numpy_available || !PyArray_Check(substitution_matrix_obj)) { |
| 1252 | PyErr_SetString(PyExc_TypeError, "substitution_matrix must be a NumPy array"); |
| 1253 | return -1; |
| 1254 | } |
| 1255 | |
| 1256 | PyArrayObject *subs_array = (PyArrayObject *)substitution_matrix_obj; |
| 1257 | if (PyArray_NDIM(subs_array) != 2 || PyArray_DIM(subs_array, 0) != 256 || PyArray_DIM(subs_array, 1) != 256) { |
| 1258 | PyErr_SetString(PyExc_ValueError, "substitution_matrix must be a 256x256 array"); |
| 1259 | return -1; |
| 1260 | } |
| 1261 | |
| 1262 | if (PyArray_TYPE(subs_array) != NPY_INT8) { |
| 1263 | PyErr_SetString(PyExc_TypeError, "substitution_matrix must have int8 dtype"); |
| 1264 | return -1; |
| 1265 | } |
| 1266 | |
| 1267 | // Check that array is C-contiguous for safe memory access |
| 1268 | if (!PyArray_IS_C_CONTIGUOUS(subs_array)) { |
| 1269 | PyErr_SetString(PyExc_ValueError, |
| 1270 | "substitution_matrix must be a C-contiguous array. Use np.ascontiguousarray() to convert."); |
| 1271 | return -1; |
| 1272 | } |
| 1273 | |
| 1274 | // Parse capabilities if provided |
| 1275 | if (capabilities_tuple) { |
| 1276 | if (parse_and_intersect_capabilities(capabilities_tuple, &capabilities) != 0) { return -1; } |
| 1277 | } |
| 1278 | |
| 1279 | // Initialize the engine |
| 1280 | sz_error_cost_t *subs_data = (sz_error_cost_t *)PyArray_DATA(subs_array); |
| 1281 | char const *error_detail = NULL; |
| 1282 | sz_status_t status = |
| 1283 | szs_smith_waterman_scores_init(subs_data, open, extend, NULL, capabilities, &self->handle, &error_detail); |
| 1284 | |
| 1285 | if (status != sz_success_k) { |
| 1286 | set_stringzilla_error(status, error_detail, "SmithWaterman initialization"); |
| 1287 | return -1; |
| 1288 | } |
| 1289 | |
| 1290 | // Create a simple checksum of the substitution matrix for the description |
| 1291 | sz_u32_t subs_checksum = 0; |
| 1292 | for (int i = 0; i < 256; i += 16) // Sample every 16th element |
| 1293 | subs_checksum += (sz_u32_t)subs_data[i * 256 + i]; // Diagonal elements |
| 1294 | |
| 1295 | snprintf(self->description, sizeof(self->description), "%X,%d,%d", subs_checksum & 0xFFFF, open, extend); |
nothing calls this directly
no test coverage detected
searching dependent graphs…