foscat 3.8.0__py3-none-any.whl → 3.9.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.
foscat/backend.py CHANGED
@@ -44,7 +44,12 @@ class foscat_backend:
44
44
 
45
45
  if self.BACKEND == "torch":
46
46
  import torch
47
- self.torch_device = torch.device("cuda") if torch.cuda.is_available() else torch.device("cpu")
47
+
48
+ self.torch_device = (
49
+ torch.device("cuda")
50
+ if torch.cuda.is_available()
51
+ else torch.device("cpu")
52
+ )
48
53
 
49
54
  self.BACKEND = self.TORCH
50
55
  self.backend = torch
@@ -383,7 +388,11 @@ class foscat_backend:
383
388
  if self.BACKEND == self.TENSORFLOW:
384
389
  return self.backend.SparseTensor(indice, w, dense_shape=dense_shape)
385
390
  if self.BACKEND == self.TORCH:
386
- return self.backend.sparse_coo_tensor(indice.T, w, dense_shape).to_sparse_csr().to(self.torch_device)
391
+ return (
392
+ self.backend.sparse_coo_tensor(indice.T, w, dense_shape)
393
+ .to_sparse_csr()
394
+ .to(self.torch_device)
395
+ )
387
396
  if self.BACKEND == self.NUMPY:
388
397
  return self.scipy.sparse.coo_matrix(
389
398
  (w, (indice[:, 0], indice[:, 1])), shape=dense_shape
@@ -406,10 +415,10 @@ class foscat_backend:
406
415
  return smat.dot(mat)
407
416
 
408
417
  # for tensorflow wrapping only
409
- def periodic_pad(self,x, pad_height, pad_width):
418
+ def periodic_pad(self, x, pad_height, pad_width):
410
419
  """
411
420
  Applies periodic ('wrap') padding to a 4D TensorFlow tensor (N, H, W, C).
412
-
421
+
413
422
  Args:
414
423
  x (tf.Tensor): Input tensor with shape (batch_size, height, width, channels).
415
424
  pad_height (tuple): Tuple (top, bottom) defining the vertical padding size.
@@ -418,40 +427,47 @@ class foscat_backend:
418
427
  Returns:
419
428
  tf.Tensor: Tensor with periodic padding applied.
420
429
  """
421
- #Vertical padding: take slices from bottom and top to wrap around
422
- top_pad = x[:, -pad_height:, :, :] # Top padding from the bottom rows
430
+ # Vertical padding: take slices from bottom and top to wrap around
431
+ top_pad = x[:, -pad_height:, :, :] # Top padding from the bottom rows
423
432
  bottom_pad = x[:, :pad_height, :, :] # Bottom padding from the top rows
424
- x_padded = self.backend.concat([top_pad, x, bottom_pad], axis=1) # Concatenate vertically
433
+ x_padded = self.backend.concat(
434
+ [top_pad, x, bottom_pad], axis=1
435
+ ) # Concatenate vertically
436
+
437
+ # Horizontal padding: take slices from right and left to wrap around
438
+ left_pad = x_padded[:, :, -pad_width:, :] # Left padding from right columns
439
+ right_pad = x_padded[:, :, :pad_width, :] # Right padding from left columns
425
440
 
426
- #Horizontal padding: take slices from right and left to wrap around
427
- left_pad = x_padded[:, :, -pad_width:, :] # Left padding from right columns
428
- right_pad = x_padded[:, :, :pad_width, :] # Right padding from left columns
429
-
430
- x_padded = self.backend.concat([left_pad, x_padded, right_pad], axis=2) # Concatenate horizontally
441
+ x_padded = self.backend.concat(
442
+ [left_pad, x_padded, right_pad], axis=2
443
+ ) # Concatenate horizontally
431
444
 
432
445
  return x_padded
433
-
446
+
434
447
  def conv2d(self, x, w, strides=[1, 1, 1, 1], padding="SAME"):
435
448
  if self.BACKEND == self.TENSORFLOW:
436
449
  kx = w.shape[0]
437
450
  ky = w.shape[1]
438
- x_padded = self.periodic_pad(x, kx // 2, ky // 2)
451
+ x_padded = self.periodic_pad(x, kx // 2, ky // 2)
439
452
  return self.backend.nn.conv2d(x_padded, w, strides=strides, padding="VALID")
440
-
453
+
441
454
  if self.BACKEND == self.TORCH:
442
455
  import torch.nn.functional as F
456
+
443
457
  lx = x.permute(0, 3, 1, 2)
444
- wx = self.backend.from_numpy(w).to(self.torch_device).permute(3, 2, 0, 1) # de (5, 5, 1, 4) à (4, 1, 5, 5)
458
+ wx = (
459
+ self.backend.from_numpy(w).to(self.torch_device).permute(3, 2, 0, 1)
460
+ ) # de (5, 5, 1, 4) à (4, 1, 5, 5)
445
461
 
446
462
  # Calculer le padding symétrique
447
463
  kx, ky = w.shape[0], w.shape[1]
448
-
464
+
449
465
  # Appliquer le padding
450
- x_padded = F.pad(lx, (ky // 2, ky // 2, kx // 2, kx // 2), mode='circular')
466
+ x_padded = F.pad(lx, (ky // 2, ky // 2, kx // 2, kx // 2), mode="circular")
451
467
 
452
468
  # Appliquer la convolution
453
- return F.conv2d(x_padded, wx, stride=1, padding=0).permute(0,2,3,1)
454
-
469
+ return F.conv2d(x_padded, wx, stride=1, padding=0).permute(0, 2, 3, 1)
470
+
455
471
  if self.BACKEND == self.NUMPY:
456
472
  res = np.zeros(
457
473
  [x.shape[0], x.shape[1], x.shape[2], w.shape[3]], dtype=x.dtype
@@ -552,15 +568,6 @@ class foscat_backend:
552
568
  return np.concatenate([x.real.flatten(), x.imag.flatten()], 0)
553
569
  else:
554
570
  return x.flatten()
555
-
556
-
557
- def bk_flatten(self, x):
558
- if self.BACKEND == self.TENSORFLOW:
559
- return self.backend.flatten(x)
560
- elif self.BACKEND == self.TORCH:
561
- return self.backend.flatten(x)
562
- else:
563
- return x.flatten()
564
571
 
565
572
  def bk_flatten(self, x):
566
573
  if self.BACKEND == self.TENSORFLOW:
@@ -570,25 +577,16 @@ class foscat_backend:
570
577
  if self.BACKEND == self.NUMPY:
571
578
  return x.flatten()
572
579
 
573
- def bk_size(self, x):
574
- if self.BACKEND == self.TENSORFLOW:
575
- return self.backend.size(x)
576
- if self.BACKEND == self.TORCH:
577
- return x.numel()
578
-
579
- if self.BACKEND == self.NUMPY:
580
- return x.size
581
-
582
580
  def bk_resize_image(self, x, shape):
583
581
  if self.BACKEND == self.TENSORFLOW:
584
582
  return self.bk_cast(self.backend.image.resize(x, shape, method="bilinear"))
585
583
 
586
584
  if self.BACKEND == self.TORCH:
587
585
  tmp = self.backend.nn.functional.interpolate(
588
- x.permute(0,3,1,2), size=shape, mode="bilinear", align_corners=False
586
+ x.permute(0, 3, 1, 2), size=shape, mode="bilinear", align_corners=False
589
587
  )
590
- return self.bk_cast(tmp.permute(0,2,3,1))
591
-
588
+ return self.bk_cast(tmp.permute(0, 2, 3, 1))
589
+
592
590
  if self.BACKEND == self.NUMPY:
593
591
  return self.bk_cast(self.backend.image.resize(x, shape, method="bilinear"))
594
592
 
@@ -882,7 +880,7 @@ class foscat_backend:
882
880
  return self.backend.constant(data).to(self.torch_device)
883
881
  if self.BACKEND == self.NUMPY:
884
882
  return data
885
-
883
+
886
884
  def bk_shape_tensor(self, shape):
887
885
  if self.BACKEND == self.TENSORFLOW:
888
886
  return self.backend.tensor(shape=shape)
@@ -1025,22 +1023,26 @@ class foscat_backend:
1025
1023
  return self.backend.fft(data)
1026
1024
  if self.BACKEND == self.NUMPY:
1027
1025
  return self.backend.fft.fft(data)
1028
-
1029
- def bk_fftn(self, data,dim=None):
1026
+
1027
+ def bk_fftn(self, data, dim=None):
1030
1028
  if self.BACKEND == self.TENSORFLOW:
1031
- #Equivalent of torch.fft.fftn(x, dim=dims) in TensorFlow
1032
- x=self.bk_complex(data,0*data)
1033
- return self.backend.signal.fftnd(x, fft_length=tuple(x.shape[d] for d in dim),axes=dim)
1029
+ # Equivalent of torch.fft.fftn(x, dim=dims) in TensorFlow
1030
+ x = self.bk_complex(data, 0 * data)
1031
+ return self.backend.signal.fftnd(
1032
+ x, fft_length=tuple(x.shape[d] for d in dim), axes=dim
1033
+ )
1034
1034
  if self.BACKEND == self.TORCH:
1035
- return self.backend.fft.fftn(data,dim=dim)
1035
+ return self.backend.fft.fftn(data, dim=dim)
1036
1036
  if self.BACKEND == self.NUMPY:
1037
1037
  return self.backend.fft.fftn(data)
1038
1038
 
1039
- def bk_ifftn(self, data,dim=None,norm=None):
1039
+ def bk_ifftn(self, data, dim=None, norm=None):
1040
1040
  if self.BACKEND == self.TENSORFLOW:
1041
- return self.backend.signal.ifftnd(data,fft_length=tuple(data.shape[d] for d in dim),axes=dim,norm=norm)
1041
+ return self.backend.signal.ifftnd(
1042
+ data, fft_length=tuple(data.shape[d] for d in dim), axes=dim, norm=norm
1043
+ )
1042
1044
  if self.BACKEND == self.TORCH:
1043
- return self.backend.fft.ifftn(data,dim=dim,norm=norm)
1045
+ return self.backend.fft.ifftn(data, dim=dim, norm=norm)
1044
1046
  if self.BACKEND == self.NUMPY:
1045
1047
  return self.backend.fft.ifftn(data)
1046
1048
 
@@ -1102,18 +1104,30 @@ class foscat_backend:
1102
1104
  if self.BACKEND == self.NUMPY:
1103
1105
  return (x > 0) * x
1104
1106
 
1105
- def bk_clip_by_value(self, x,xmin,xmax):
1107
+ def bk_clip_by_value(self, x, xmin, xmax):
1106
1108
  if isinstance(x, np.ndarray):
1107
- x = np.clip(x,xmin,xmax)
1109
+ x = np.clip(x, xmin, xmax)
1108
1110
  if self.BACKEND == self.TENSORFLOW:
1109
- return self.backend.clip_by_value(x,xmin,xmax)
1111
+ return self.backend.clip_by_value(x, xmin, xmax)
1110
1112
  if self.BACKEND == self.TORCH:
1111
- x = self.backend.tensor(x, dtype=self.backend.float32) if not isinstance(x, self.backend.Tensor) else x
1112
- xmin = self.backend.tensor(xmin, dtype=self.backend.float32) if not isinstance(xmin, self.backend.Tensor) else xmin
1113
- xmax = self.backend.tensor(xmax, dtype=self.backend.float32) if not isinstance(xmax, self.backend.Tensor) else xmax
1113
+ x = (
1114
+ self.backend.tensor(x, dtype=self.backend.float32)
1115
+ if not isinstance(x, self.backend.Tensor)
1116
+ else x
1117
+ )
1118
+ xmin = (
1119
+ self.backend.tensor(xmin, dtype=self.backend.float32)
1120
+ if not isinstance(xmin, self.backend.Tensor)
1121
+ else xmin
1122
+ )
1123
+ xmax = (
1124
+ self.backend.tensor(xmax, dtype=self.backend.float32)
1125
+ if not isinstance(xmax, self.backend.Tensor)
1126
+ else xmax
1127
+ )
1114
1128
  return self.backend.clamp(x, min=xmin, max=xmax)
1115
1129
  if self.BACKEND == self.NUMPY:
1116
- return self.backend.clip(x,xmin,xmax)
1130
+ return self.backend.clip(x, xmin, xmax)
1117
1131
 
1118
1132
  def bk_cast(self, x):
1119
1133
  if isinstance(x, np.float64):
@@ -1164,28 +1178,28 @@ class foscat_backend:
1164
1178
 
1165
1179
  if self.BACKEND == self.NUMPY:
1166
1180
  return x.astype(out_type)
1167
-
1168
- def bk_variable(self,x):
1181
+
1182
+ def bk_variable(self, x):
1169
1183
  if self.BACKEND == self.TENSORFLOW:
1170
1184
  return self.backend.Variable(x)
1171
-
1185
+
1172
1186
  return self.bk_cast(x)
1173
-
1174
- def bk_assign(self,x,y):
1187
+
1188
+ def bk_assign(self, x, y):
1175
1189
  if self.BACKEND == self.TENSORFLOW:
1176
1190
  x.assign(y)
1177
- x=y
1178
-
1179
- def bk_constant(self,x):
1191
+ x = y
1192
+
1193
+ def bk_constant(self, x):
1180
1194
  if self.BACKEND == self.TENSORFLOW:
1181
1195
  return self.backend.constant(x)
1182
-
1196
+
1183
1197
  return self.bk_cast(x)
1184
-
1185
- def to_numpy(self,x):
1198
+
1199
+ def to_numpy(self, x):
1186
1200
  if isinstance(x, np.ndarray):
1187
1201
  return x
1188
-
1202
+
1189
1203
  if self.BACKEND == self.NUMPY:
1190
1204
  return x
1191
1205
  if self.BACKEND == self.TENSORFLOW: