spacekit 1.1.4__tar.gz → 1.1.5__tar.gz

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.
Files changed (81) hide show
  1. {spacekit-1.1.4 → spacekit-1.1.5}/LICENSE +1 -1
  2. {spacekit-1.1.4/spacekit.egg-info → spacekit-1.1.5}/PKG-INFO +2 -2
  3. {spacekit-1.1.4 → spacekit-1.1.5}/README.md +1 -1
  4. {spacekit-1.1.4 → spacekit-1.1.5}/pyproject.toml +1 -0
  5. {spacekit-1.1.4 → spacekit-1.1.5}/setup.cfg +1 -1
  6. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/analyzer/compute.py +98 -40
  7. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/analyzer/explore.py +57 -54
  8. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/analyzer/scan.py +32 -25
  9. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/analyzer/track.py +14 -9
  10. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/analyzer/validate.py +22 -20
  11. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/builder/architect.py +55 -47
  12. spacekit-1.1.5/spacekit/builder/blueprints.py +211 -0
  13. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/dashboard/cal/__init__.py +1 -3
  14. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/dashboard/cal/config.py +0 -2
  15. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/dashboard/cal/eda.py +2 -2
  16. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/dashboard/cal/eval.py +2 -3
  17. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/dashboard/cal/index.py +9 -9
  18. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/dashboard/cal/nodegraph.py +10 -9
  19. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/dashboard/cal/pred.py +2 -3
  20. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/dashboard/svm/eda.py +2 -2
  21. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/dashboard/svm/eval.py +2 -3
  22. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/dashboard/svm/index.py +8 -8
  23. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/dashboard/svm/pred.py +1 -2
  24. spacekit-1.1.5/spacekit/datasets/__init__.py +14 -0
  25. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/datasets/_base.py +3 -3
  26. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/datasets/beam.py +6 -5
  27. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/extractor/load.py +30 -22
  28. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/extractor/radio.py +30 -31
  29. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/extractor/scrape.py +90 -100
  30. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/generator/augment.py +2 -3
  31. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/generator/draw.py +31 -31
  32. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/logger/log.py +19 -41
  33. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/preprocessor/encode.py +104 -71
  34. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/preprocessor/ingest.py +40 -47
  35. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/preprocessor/prep.py +44 -23
  36. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/preprocessor/scrub.py +68 -62
  37. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/preprocessor/transform.py +52 -49
  38. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/skopes/hst/cal/predict.py +18 -9
  39. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/skopes/hst/cal/train.py +42 -38
  40. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/skopes/hst/cal/validate.py +11 -7
  41. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/skopes/hst/svm/corrupt.py +13 -15
  42. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/skopes/hst/svm/predict.py +8 -6
  43. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/skopes/hst/svm/prep.py +2 -1
  44. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/skopes/hst/svm/train.py +26 -25
  45. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/skopes/jwst/cal/predict.py +37 -38
  46. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/skopes/jwst/cal/train.py +28 -26
  47. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/skopes/kepler/light_curves.py +6 -5
  48. {spacekit-1.1.4 → spacekit-1.1.5/spacekit.egg-info}/PKG-INFO +2 -2
  49. spacekit-1.1.4/spacekit/builder/blueprints.py +0 -211
  50. spacekit-1.1.4/spacekit/datasets/__init__.py +0 -21
  51. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/__init__.py +0 -0
  52. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/analyzer/__init__.py +0 -0
  53. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/builder/__init__.py +0 -0
  54. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/builder/trained_networks/__init__.py +0 -0
  55. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/builder/trained_networks/hst_cal.zip +0 -0
  56. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/builder/trained_networks/jwst_cal.zip +0 -0
  57. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/builder/trained_networks/svm_align.zip +0 -0
  58. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/dashboard/__init__.py +0 -0
  59. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/dashboard/cal/app.py +0 -0
  60. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/dashboard/svm/__init__.py +0 -0
  61. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/dashboard/svm/app.py +0 -0
  62. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/dashboard/svm/config.py +1 -1
  63. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/datasets/meta.py +0 -0
  64. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/extractor/__init__.py +0 -0
  65. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/generator/__init__.py +0 -0
  66. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/logger/__init__.py +0 -0
  67. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/preprocessor/__init__.py +0 -0
  68. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/skopes/__init__.py +0 -0
  69. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/skopes/hst/__init__.py +0 -0
  70. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/skopes/hst/cal/__init__.py +0 -0
  71. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/skopes/hst/cal/config.py +0 -0
  72. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/skopes/hst/svm/__init__.py +0 -0
  73. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/skopes/jwst/__init__.py +0 -0
  74. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/skopes/jwst/cal/__init__.py +0 -0
  75. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/skopes/jwst/cal/config.py +0 -0
  76. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit/skopes/kepler/__init__.py +0 -0
  77. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit.egg-info/SOURCES.txt +0 -0
  78. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit.egg-info/dependency_links.txt +0 -0
  79. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit.egg-info/not-zip-safe +0 -0
  80. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit.egg-info/requires.txt +0 -0
  81. {spacekit-1.1.4 → spacekit-1.1.5}/spacekit.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2024 Ru Keïn
3
+ Copyright (c) 2026 Ru Keïn
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: spacekit
3
- Version: 1.1.4
3
+ Version: 1.1.5
4
4
  Summary: Astronomical Data Science and Machine Learning Toolkit
5
5
  Home-page: https://github.com/spacetelescope/spacekit
6
6
  Author: Ru Keïn
@@ -185,7 +185,7 @@ ens.batch_fit()
185
185
 
186
186
  # Save Training Metrics
187
187
  outputs = f"data/{date_timestamp}"
188
- com = ComputeBinary(builder=ens, res_path=f"{outputs}/results/test")
188
+ com = ComputeBinary(builder=ens, res_path=f"{outputs}/results/test", classes=["aligned", "misaligned"])
189
189
  com.calculate_results()
190
190
  ```
191
191
  # Load and plot metrics to evaluate and compare model performance
@@ -127,7 +127,7 @@ ens.batch_fit()
127
127
 
128
128
  # Save Training Metrics
129
129
  outputs = f"data/{date_timestamp}"
130
- com = ComputeBinary(builder=ens, res_path=f"{outputs}/results/test")
130
+ com = ComputeBinary(builder=ens, res_path=f"{outputs}/results/test", classes=["aligned", "misaligned"])
131
131
  com.calculate_results()
132
132
  ```
133
133
  # Load and plot metrics to evaluate and compare model performance
@@ -21,6 +21,7 @@ exclude = [
21
21
  [tool.ruff.lint]
22
22
  ignore = [
23
23
  'E741', # ambiguous variable name
24
+ 'UP017', # Use `datetime.UTC` alias
24
25
  ]
25
26
 
26
27
  [tool.ruff.lint.per-file-ignores]
@@ -1,6 +1,6 @@
1
1
  [metadata]
2
2
  name = spacekit
3
- version = 1.1.4
3
+ version = 1.1.5
4
4
  author = Ru Keïn
5
5
  author_email = rkein@stsci.edu
6
6
  license = MIT
@@ -1,26 +1,28 @@
1
- import os
1
+ import datetime as dt
2
2
  import glob
3
3
  import itertools
4
+ import os
5
+
4
6
  import numpy as np
5
7
  import pandas as pd
6
- import datetime as dt
7
8
  from sklearn.metrics import (
8
9
  auc,
9
- roc_curve,
10
- roc_auc_score,
11
- precision_recall_curve,
12
10
  average_precision_score,
13
11
  classification_report,
14
12
  confusion_matrix,
13
+ precision_recall_curve,
14
+ roc_auc_score,
15
+ roc_curve,
15
16
  )
16
17
  from tensorflow.python.ops.numpy_ops import np_config
18
+
19
+ from spacekit.extractor.load import load_multitype_data, save_multitype_data
17
20
  from spacekit.logger.log import Logger
18
- from spacekit.extractor.load import save_multitype_data, load_multitype_data
19
21
 
20
22
  try:
21
- import plotly.graph_objects as go
22
23
  import matplotlib as mpl
23
24
  import matplotlib.pyplot as plt
25
+ import plotly.graph_objects as go
24
26
 
25
27
  font_dict = {"family": "monospace", "size": 16} # Titillium Web
26
28
  mpl.rc("font", **font_dict)
@@ -41,7 +43,7 @@ def check_viz_imports():
41
43
  return go is not None
42
44
 
43
45
 
44
- class Computer(object):
46
+ class Computer:
45
47
  def __init__(
46
48
  self,
47
49
  algorithm,
@@ -150,7 +152,7 @@ class Computer(object):
150
152
  self.y_test = builder.y_val
151
153
  self.X_train = builder.X_test
152
154
  self.y_train = builder.y_test
153
- except Exception as e:
155
+ except AttributeError as e:
154
156
  print(e)
155
157
  print("Validation attributes not set.")
156
158
  else:
@@ -175,8 +177,8 @@ class Computer(object):
175
177
  Outputs created by their respective subclasses using the ``make_outputs`` method.
176
178
  """
177
179
  if self.res_path is None:
178
- timestamp = int(dt.datetime.now().timestamp())
179
- datestamp = dt.date.fromtimestamp(timestamp).isoformat()
180
+ timestamp = int(dt.datetime.now(tz=dt.timezone.utc).timestamp())
181
+ datestamp = dt.datetime.fromtimestamp(timestamp, tz=dt.timezone.utc).date().isoformat()
180
182
  prefix = str(datestamp) + "-" + str(timestamp)
181
183
  self.res_path = os.path.join(os.getcwd(), prefix, "results", self.algorithm)
182
184
  save_multitype_data(
@@ -202,7 +204,7 @@ class Computer(object):
202
204
  if self.res_path is None:
203
205
  try:
204
206
  self.res_path = glob.glob(f"data/*/results/{self.algorithm}")[0]
205
- except Exception as e:
207
+ except IndexError as e:
206
208
  self.log.error(f"No results found @ {self.res_path} \n", e)
207
209
  return outputs
208
210
  if os.path.exists(self.res_path):
@@ -280,7 +282,6 @@ class Computer(object):
280
282
  self.roc_fig = self.make_roc_curve()
281
283
  self.pr_fig = self.make_pr_curve()
282
284
  self.cm_fig, self.cmx_norm = self.fusion_matrix(self.cmx, self.classes)
283
- return self
284
285
 
285
286
  # Matplotlib "static" alternative to interactive plotly version
286
287
  def roc_plots(self):
@@ -311,11 +312,11 @@ class Computer(object):
311
312
  ax = axes[0]
312
313
  ax.plot(thresholds, 1.0 - fpr)
313
314
  ax.plot(thresholds, tpr)
314
- ax.set_title("Crossover at {0:.2f}, Specificity {1:.2f}".format(crossover_cutoff, crossover_specificity))
315
+ ax.set_title(f"Crossover at {crossover_cutoff:.2f}, Specificity {crossover_specificity:.2f}")
315
316
 
316
317
  ax = axes[1]
317
318
  ax.plot(fpr, tpr)
318
- ax.set_title("ROC area under curve: {0:.2f}".format(roc_auc_score(y_true, y_hat)))
319
+ ax.set_title(f"ROC area under curve: {roc_auc_score(y_true, y_hat):.2f}")
319
320
  if self.show:
320
321
  fig.show()
321
322
 
@@ -330,7 +331,7 @@ class Computer(object):
330
331
  ROC-AUC interactive figure plot
331
332
  """
332
333
  fig = go.Figure()
333
- fig.add_shape(type="line", line=dict(dash="dash"), x0=0, x1=1, y0=0, y1=1)
334
+ fig.add_shape(type="line", line={"dash":"dash"}, x0=0, x1=1, y0=0, y1=1)
334
335
 
335
336
  if regression is True:
336
337
  if self.y_pred_dummies is None:
@@ -354,8 +355,8 @@ class Computer(object):
354
355
  title_text=title,
355
356
  xaxis_title="False Positive Rate",
356
357
  yaxis_title="True Positive Rate",
357
- yaxis=dict(scaleanchor="x", scaleratio=1),
358
- xaxis=dict(constrain="domain"),
358
+ yaxis={"scaleanchor":"x", "scaleratio":1},
359
+ xaxis={"constrain":"domain"},
359
360
  width=800,
360
361
  height=500,
361
362
  paper_bgcolor="#242a44",
@@ -367,8 +368,27 @@ class Computer(object):
367
368
  return fig
368
369
 
369
370
  @staticmethod
370
- def get_bin_estimate(y_val, n_classes=4, thresholds=[0, 12, 225, 950]):
371
+ def get_bin_estimate(y_val, n_classes=4, thresholds=None):
372
+ """_summary_
373
+
374
+ Parameters
375
+ ----------
376
+ y_val : int
377
+ predicted value
378
+ n_classes : int, optional
379
+ number of target classes, by default 4
380
+ thresholds : list, optional
381
+ target class threshold values (length of list much match n_classes), by default None
382
+
383
+ Returns
384
+ -------
385
+ int
386
+ target class bin estimate
387
+ """
388
+ thresholds = [0, 12, 225, 950] if thresholds is None else thresholds
371
389
  thresholds = sorted(thresholds, reverse=True)
390
+ if len(thresholds) != n_classes:
391
+ raise IndexError(f"n_classes = {n_classes} does not match length of thresholds list: {len(thresholds)}")
372
392
  for i in list(range(len(thresholds))):
373
393
  if y_val >= thresholds[i]:
374
394
  return n_classes - i - 1
@@ -388,7 +408,7 @@ class Computer(object):
388
408
  self.classes = y_onehot.columns
389
409
 
390
410
  def regression_roc(self, fig):
391
- fpr, tpr, self.roc_auc = dict(), dict(), dict()
411
+ fpr, tpr, self.roc_auc = {}, {}, {}
392
412
  for i in list(range(len(self.classes))):
393
413
  y_true = self.y_test_dummies[:, i]
394
414
  y_hat = self.y_pred_dummies.iloc[:, i]
@@ -399,7 +419,7 @@ class Computer(object):
399
419
  return fig
400
420
 
401
421
  def regression_recall(self, fig):
402
- precision, recall, self.pr = dict(), dict(), dict()
422
+ precision, recall, self.pr = {}, {}, {}
403
423
  for i in list(range(len(self.classes))):
404
424
  y_true = self.y_test_dummies[:, i]
405
425
  y_hat = self.y_pred_dummies.iloc[:, i]
@@ -419,7 +439,7 @@ class Computer(object):
419
439
  """
420
440
 
421
441
  fig = go.Figure()
422
- fig.add_shape(type="line", line=dict(dash="dash"), x0=0, x1=1, y0=1, y1=0)
442
+ fig.add_shape(type="line", line={"dash":"dash"}, x0=0, x1=1, y0=1, y1=0)
423
443
 
424
444
  if regression is True:
425
445
  if self.y_pred_dummies is None:
@@ -443,8 +463,8 @@ class Computer(object):
443
463
  title_text=title,
444
464
  xaxis_title="Recall",
445
465
  yaxis_title="Precision",
446
- yaxis=dict(scaleanchor="x", scaleratio=1),
447
- xaxis=dict(constrain="domain"),
466
+ yaxis={"scaleanchor":"x", "scaleratio":1},
467
+ xaxis={"constrain":"domain"},
448
468
  width=800,
449
469
  height=500,
450
470
  paper_bgcolor="#242a44",
@@ -472,13 +492,13 @@ class Computer(object):
472
492
  x=n_epochs,
473
493
  y=acc_train,
474
494
  name=f"Training {keys[1].title()}",
475
- marker=dict(color="#119dff"),
495
+ marker={"color":"#119dff"},
476
496
  ),
477
497
  go.Scatter(
478
498
  x=n_epochs,
479
499
  y=acc_test,
480
500
  name=f"Test {keys[3].title()}",
481
- marker=dict(color="#66c2a5"),
501
+ marker={"color":"#66c2a5"},
482
502
  ),
483
503
  ]
484
504
  layout = go.Layout(
@@ -523,13 +543,13 @@ class Computer(object):
523
543
  x=n_epochs,
524
544
  y=loss_train,
525
545
  name=f"Training {keys[0].title()}",
526
- marker=dict(color="#119dff"),
546
+ marker={"color":"#119dff"},
527
547
  ),
528
548
  go.Scatter(
529
549
  x=n_epochs,
530
550
  y=loss_test,
531
551
  name=f"Test {keys[2].title()}",
532
- marker=dict(color="#66c2a5"),
552
+ marker={"color":"#66c2a5"},
533
553
  ),
534
554
  ]
535
555
  layout = go.Layout(
@@ -571,7 +591,7 @@ class Computer(object):
571
591
  title = "Residual Error"
572
592
  if desc:
573
593
  title += f" - {desc}"
574
- data = go.Scatter(x=y, y=p, name="y-y_hat", mode="markers", marker=dict(color="red"))
594
+ data = go.Scatter(x=y, y=p, name="y-y_hat", mode="markers", marker={"color":"red"})
575
595
  layout = go.Layout(
576
596
  title=title,
577
597
  xaxis={"title": "y (ground truth)"},
@@ -585,7 +605,7 @@ class Computer(object):
585
605
  fig = go.Figure(data=data, layout=layout)
586
606
  fig.add_shape(
587
607
  type="line",
588
- line=dict(dash="dash"),
608
+ line={"dash":"dash"},
589
609
  x0=y.min(),
590
610
  y0=y.min(),
591
611
  x1=y.max(),
@@ -683,14 +703,24 @@ class ComputeClassifier(Computer):
683
703
 
684
704
  Parameters
685
705
  ----------
686
- Computer : Class object
687
- spacekit.analyzer.compute.Computer object
706
+ algorithm : str, optional
707
+ Algorithm used for classification such as 'clf', 'binary' or 'linreg', by default "clf"
708
+ classes : list or tuple, optional
709
+ String labels for the target classes, by default None
710
+ res_path : str, optional
711
+ Path to the directory where results will be saved, by default "results/mem_bin"
712
+ show : bool, optional
713
+ Whether to display plots, by default False
714
+ validation : bool, optional
715
+ Whether the compute object is for a validation set, by default False
716
+ name : str, optional
717
+ Name of the compute object, by default "ComputeClassifier"
688
718
  """
689
719
 
690
720
  def __init__(
691
721
  self,
692
722
  algorithm="clf",
693
- classes=["2g", "8g", "16g", "64g"],
723
+ classes=None,
694
724
  res_path="results/mem_bin",
695
725
  show=False,
696
726
  validation=False,
@@ -705,7 +735,7 @@ class ComputeClassifier(Computer):
705
735
  name=name,
706
736
  **log_kws,
707
737
  )
708
- self.classes = classes
738
+ self.classes = ["2g", "8g", "16g", "64g"] if classes is None else list(classes)
709
739
 
710
740
  def make_outputs(self, dl=True):
711
741
  """Store computed results into a dictionary, and optionally save to disk.
@@ -819,20 +849,38 @@ class ComputeBinary(ComputeClassifier):
819
849
 
820
850
  Parameters
821
851
  ----------
822
- ComputeClassifier : Subclass object
823
- spacekit.analyzer.compute.ComputeClassifier object
852
+ builder : ComputeClassifier object, optional
853
+ Existing ComputeClassifier object with instantiated attributes, by default None
854
+ algorithm : str, optional
855
+ Algorithm kind, by default "binary"
856
+ classes : list or tuple, optional
857
+ String labels for the target classes, by default None, by default None
858
+ res_path : str, optional
859
+ Path to store results, by default "results/svm"
860
+ show : bool, optional
861
+ Whether to display plots, by default False
862
+ validation : bool, optional
863
+ Whether to perform validation, by default False
864
+
865
+ Raises
866
+ ------
867
+ AttributeError
868
+ Raised when the `classes` parameter is not a list or tuple of exactly two strings.
824
869
  """
825
870
 
826
871
  def __init__(
827
872
  self,
828
873
  builder=None,
829
874
  algorithm="binary",
830
- classes=["aligned", "misaligned"],
875
+ classes=None,
831
876
  res_path="results/svm",
832
877
  show=False,
833
878
  validation=False,
834
879
  **log_kws,
835
880
  ):
881
+ classes = ["aligned", "misaligned"] if classes is None else classes
882
+ if not isinstance(classes, (list, tuple)) or len(classes) != 2:
883
+ raise AttributeError("Binary classifier requires `classes` to be a list/tuple of exactly two strings to be used as target class names.")
836
884
  super().__init__(
837
885
  algorithm=algorithm,
838
886
  classes=classes,
@@ -881,15 +929,25 @@ class ComputeMulti(ComputeClassifier):
881
929
 
882
930
  Parameters
883
931
  ----------
884
- ComputeClassifier : Subclass object
885
- spacekit.analyzer.compute.ComputeClassifier object
932
+ builder : ComputeClassifier object, optional
933
+ Existing ComputeClassifier object with instantiated attributes, by default None
934
+ algorithm : str, optional
935
+ Algorithm kind, by default "multiclass"
936
+ classes : list or tuple, optional
937
+ String labels for the target classes, by default None
938
+ res_path : str, optional
939
+ Path to store results, by default "results/svm"
940
+ show : bool, optional
941
+ Whether to display plots, by default False
942
+ validation : bool, optional
943
+ Whether to perform validation, by default False
886
944
  """
887
945
 
888
946
  def __init__(
889
947
  self,
890
948
  builder=None,
891
949
  algorithm="multiclass",
892
- classes=["2g", "8g", "16g", "64g"],
950
+ classes=None,
893
951
  res_path="results/mem_bin",
894
952
  show=False,
895
953
  validation=False,