featrixsphere 0.1.560__py3-none-any.whl → 0.2.1235__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.
@@ -1,629 +0,0 @@
1
-
2
- class PredictionGrid:
3
- """
4
- Grid-based prediction batch with automatic matrix building and visualization.
5
-
6
- Perfect for exploring prediction surfaces across 1-3 dimensions with automatic plotting.
7
- Collects all predictions and batches them for efficiency.
8
-
9
- Usage:
10
- # 2D parameter sweep with automatic plotting
11
- grid = client.predict_grid(session_id, degrees_of_freedom=2)
12
-
13
- # Fill grid (records are collected, not predicted yet)
14
- for i, spend in enumerate([100, 250, 500]):
15
- for j, campaign in enumerate(["search", "display"]):
16
- record = {"spend": spend, "campaign_type": campaign}
17
- grid.predict(record, grid_position=(i, j))
18
-
19
- # Process all predictions in one batch
20
- grid.process_batch()
21
-
22
- # Now plot results
23
- grid.plot_heatmap() # Automatic heatmap
24
- grid.plot_3d() # 3D surface plot
25
- """
26
-
27
- def __init__(self, session_id: str, client: 'FeatrixSphereClient', degrees_of_freedom: int,
28
- grid_shape: tuple = None, target_column: str = None):
29
- self.session_id = session_id
30
- self.client = client
31
- self.degrees_of_freedom = degrees_of_freedom
32
- self.target_column = target_column
33
-
34
- # Initialize grid matrix based on degrees of freedom
35
- if grid_shape:
36
- self.grid_shape = grid_shape
37
- else:
38
- # Default grid sizes
39
- default_sizes = {1: (20,), 2: (10, 10), 3: (8, 8, 8)}
40
- self.grid_shape = default_sizes.get(degrees_of_freedom, (10,) * degrees_of_freedom)
41
-
42
- # Initialize matrices for different data types
43
- self._prediction_matrix = {} # class_name -> matrix
44
- self._confidence_matrix = None
45
- self._filled_positions = set()
46
-
47
- # Batch collection system
48
- self._pending_records = {} # grid_position -> record
49
- self._position_to_index = {} # grid_position -> batch_index
50
- self._batch_processed = False
51
-
52
- # Metadata for plotting
53
- self._axis_labels = [f"Param {i+1}" for i in range(degrees_of_freedom)]
54
- self._axis_values = [[] for _ in range(degrees_of_freedom)]
55
- self._colormap = 'viridis'
56
-
57
- # Statistics
58
- self._stats = {'predictions': 0, 'batched': 0, 'errors': 0}
59
-
60
- def predict(self, record: Dict[str, Any], grid_position: tuple) -> Dict[str, str]:
61
- """
62
- Add record to grid for batch processing.
63
-
64
- Args:
65
- record: Record to predict
66
- grid_position: Tuple of grid coordinates (i,) for 1D, (i,j) for 2D, (i,j,k) for 3D
67
-
68
- Returns:
69
- Status message about queuing for batch processing
70
- """
71
- if len(grid_position) != self.degrees_of_freedom:
72
- error_msg = f"Grid position must have {self.degrees_of_freedom} dimensions, got {len(grid_position)}"
73
- raise ValueError(self.client._format_error_with_version(error_msg, f"predict_grid_session_{self.session_id}"))
74
-
75
- # Check bounds
76
- for i, pos in enumerate(grid_position):
77
- if pos >= self.grid_shape[i]:
78
- error_msg = f"Grid position {pos} exceeds dimension {i} size {self.grid_shape[i]}"
79
- raise ValueError(self.client._format_error_with_version(error_msg, f"predict_grid_session_{self.session_id}"))
80
-
81
- # Store record for batch processing
82
- self._pending_records[grid_position] = record
83
-
84
- return {
85
- "status": "queued_for_batch",
86
- "grid_position": grid_position,
87
- "total_queued": len(self._pending_records),
88
- "message": f"Record queued at position {grid_position}. Call process_batch() to run predictions."
89
- }
90
-
91
- def process_batch(self, show_progress: bool = True) -> Dict[str, Any]:
92
- """
93
- Process all queued records in a single batch prediction.
94
-
95
- Args:
96
- show_progress: Whether to show progress during batch processing
97
-
98
- Returns:
99
- Batch processing results
100
- """
101
- if not self._pending_records:
102
- return {"message": "No records to process", "processed": 0}
103
-
104
- if self._batch_processed:
105
- return {"message": "Batch already processed", "processed": len(self._filled_positions)}
106
-
107
- # Convert grid records to list for batch processing
108
- records_list = []
109
- position_mapping = {}
110
-
111
- for grid_pos, record in self._pending_records.items():
112
- batch_index = len(records_list)
113
- records_list.append(record)
114
- position_mapping[batch_index] = grid_pos
115
- self._position_to_index[grid_pos] = batch_index
116
-
117
- if show_progress:
118
- print(f"🚀 Processing {len(records_list)} grid positions in batch...")
119
-
120
- # Use existing batch prediction system
121
- try:
122
- batch_results = self.client.predict_records(
123
- session_id=self.session_id,
124
- records=records_list,
125
- target_column=self.target_column,
126
- show_progress_bar=show_progress
127
- )
128
-
129
- # Process results and populate matrices
130
- predictions = batch_results.get('predictions', [])
131
- successful = 0
132
- failed = 0
133
-
134
- for prediction in predictions:
135
- row_index = prediction.get('row_index', 0)
136
- if row_index in position_mapping:
137
- grid_pos = position_mapping[row_index]
138
-
139
- if 'prediction' in prediction and prediction['prediction']:
140
- prediction_probs = prediction['prediction']
141
-
142
- # Initialize matrices if first successful prediction
143
- if not self._prediction_matrix:
144
- self._initialize_matrices(prediction_probs.keys())
145
-
146
- # Store prediction results in matrices
147
- for class_name, probability in prediction_probs.items():
148
- self._prediction_matrix[class_name][grid_pos] = probability
149
-
150
- # Store confidence (highest probability)
151
- max_class = max(prediction_probs, key=prediction_probs.get)
152
- confidence = prediction_probs[max_class]
153
- self._confidence_matrix[grid_pos] = confidence
154
-
155
- # Mark position as filled
156
- self._filled_positions.add(grid_pos)
157
- successful += 1
158
- else:
159
- failed += 1
160
- self._stats['errors'] += 1
161
-
162
- self._stats['predictions'] = successful
163
- self._stats['batched'] = len(records_list)
164
- self._batch_processed = True
165
-
166
- # Clear pending records
167
- self._pending_records.clear()
168
-
169
- if show_progress:
170
- print(f"✅ Batch processing complete: {successful} successful, {failed} failed")
171
- print(f"📊 Grid filled: {len(self._filled_positions)} positions")
172
-
173
- return {
174
- "processed": len(records_list),
175
- "successful": successful,
176
- "failed": failed,
177
- "batch_results": batch_results
178
- }
179
-
180
- except Exception as e:
181
- self._stats['errors'] += len(records_list)
182
- raise Exception(f"Error processing grid batch: {str(e)}")
183
-
184
- def _initialize_matrices(self, class_names: list):
185
- """Initialize prediction matrices for each class."""
186
- import numpy as np
187
-
188
- for class_name in class_names:
189
- self._prediction_matrix[class_name] = np.full(self.grid_shape, np.nan)
190
-
191
- self._confidence_matrix = np.full(self.grid_shape, np.nan)
192
-
193
- def set_axis_labels(self, labels: list):
194
- """Set custom labels for axes."""
195
- if len(labels) != self.degrees_of_freedom:
196
- raise ValueError(f"Must provide {self.degrees_of_freedom} labels")
197
- self._axis_labels = labels
198
-
199
- def set_axis_values(self, axis_index: int, values: list):
200
- """Set actual values for an axis (for proper tick labels)."""
201
- if axis_index >= self.degrees_of_freedom:
202
- raise ValueError(f"Axis index {axis_index} exceeds degrees of freedom {self.degrees_of_freedom}")
203
- self._axis_values[axis_index] = values
204
-
205
- def plot_heatmap(self, class_name: str = None, figsize: tuple = (10, 8), title: str = None):
206
- """
207
- Plot 2D heatmap of prediction probabilities.
208
-
209
- Args:
210
- class_name: Specific class to plot (default: highest probability class)
211
- figsize: Figure size
212
- title: Custom title
213
- """
214
- if self.degrees_of_freedom != 2:
215
- raise ValueError("Heatmap plotting only supports 2D grids")
216
-
217
- if not self._batch_processed:
218
- raise ValueError("Must call process_batch() first")
219
-
220
- try:
221
- import matplotlib.pyplot as plt
222
- import numpy as np
223
- except ImportError:
224
- raise ImportError("matplotlib required for plotting. Install with: pip install matplotlib")
225
-
226
- if not self._prediction_matrix:
227
- raise ValueError("No predictions processed yet. Call process_batch() first.")
228
-
229
- # Choose class to plot
230
- if class_name is None:
231
- # Use the class with highest average probability
232
- avg_probs = {}
233
- for cls, matrix in self._prediction_matrix.items():
234
- avg_probs[cls] = np.nanmean(matrix)
235
- class_name = max(avg_probs, key=avg_probs.get)
236
-
237
- matrix = self._prediction_matrix[class_name]
238
-
239
- # Create plot
240
- fig, ax = plt.subplots(figsize=figsize)
241
-
242
- # Transpose matrix for correct matplotlib display orientation
243
- # matplotlib imshow: first dimension = Y-axis (vertical), second = X-axis (horizontal)
244
- # So we need to transpose to get axis 0 on X-axis and axis 1 on Y-axis
245
- display_matrix = matrix.T
246
-
247
- # Plot heatmap with transposed matrix
248
- im = ax.imshow(display_matrix, cmap=self._colormap, aspect='auto', origin='lower')
249
-
250
- # Set labels (axis 0 = X-axis, axis 1 = Y-axis after transpose)
251
- ax.set_xlabel(self._axis_labels[0])
252
- ax.set_ylabel(self._axis_labels[1])
253
-
254
- # Set tick labels if axis values provided (adjusted for transpose)
255
- if self._axis_values[0]:
256
- ax.set_xticks(range(len(self._axis_values[0])))
257
- ax.set_xticklabels(self._axis_values[0])
258
- if self._axis_values[1]:
259
- ax.set_yticks(range(len(self._axis_values[1])))
260
- ax.set_yticklabels(self._axis_values[1])
261
-
262
- # Add colorbar
263
- cbar = plt.colorbar(im, ax=ax)
264
- cbar.set_label(f'Probability of {class_name}')
265
-
266
- # Set title
267
- if title is None:
268
- title = f'Prediction Heatmap: {class_name}'
269
- ax.set_title(title)
270
-
271
- plt.tight_layout()
272
- return fig, ax
273
-
274
- def plot_3d(self, class_name: str = None, figsize: tuple = (12, 9), title: str = None,
275
- value_filter: tuple = None, opacity: float = 0.8, show_wireframe: bool = False):
276
- """
277
- Plot 3D surface of prediction probabilities with filtering and opacity controls.
278
-
279
- Args:
280
- class_name: Specific class to plot (default: highest probability class)
281
- figsize: Figure size
282
- title: Custom title
283
- value_filter: Tuple (min_value, max_value) to filter displayed predictions
284
- opacity: Surface opacity (0.0 = transparent, 1.0 = opaque)
285
- show_wireframe: Whether to show wireframe overlay for better shape visibility
286
- """
287
- if self.degrees_of_freedom != 2:
288
- raise ValueError("3D surface plotting only supports 2D grids")
289
-
290
- if not self._batch_processed:
291
- raise ValueError("Must call process_batch() first")
292
-
293
- try:
294
- import matplotlib.pyplot as plt
295
- import numpy as np
296
- from mpl_toolkits.mplot3d import Axes3D
297
- except ImportError:
298
- raise ImportError("matplotlib required for plotting. Install with: pip install matplotlib")
299
-
300
- if not self._prediction_matrix:
301
- raise ValueError("No predictions processed yet. Call process_batch() first.")
302
-
303
- # Choose class to plot
304
- if class_name is None:
305
- avg_probs = {}
306
- for cls, matrix in self._prediction_matrix.items():
307
- avg_probs[cls] = np.nanmean(matrix)
308
- class_name = max(avg_probs, key=avg_probs.get)
309
-
310
- matrix = self._prediction_matrix[class_name].copy()
311
-
312
- # Apply value filter if specified
313
- if value_filter is not None:
314
- min_val, max_val = value_filter
315
- # Mask values outside the filter range
316
- mask = (matrix < min_val) | (matrix > max_val)
317
- matrix[mask] = np.nan
318
-
319
- # Create meshgrid with proper axis orientation
320
- x = np.arange(matrix.shape[0]) # axis 0
321
- y = np.arange(matrix.shape[1]) # axis 1
322
- X, Y = np.meshgrid(x, y, indexing='ij')
323
-
324
- # Create 3D plot
325
- fig = plt.figure(figsize=figsize)
326
- ax = fig.add_subplot(111, projection='3d')
327
-
328
- # Plot surface with specified opacity
329
- surf = ax.plot_surface(X, Y, matrix, cmap=self._colormap, alpha=opacity)
330
-
331
- # Add wireframe if requested (helps see shape)
332
- if show_wireframe:
333
- ax.plot_wireframe(X, Y, matrix, alpha=0.3, color='black', linewidth=0.5)
334
-
335
- # Set labels (axis 0 = X-axis, axis 1 = Y-axis)
336
- ax.set_xlabel(self._axis_labels[0])
337
- ax.set_ylabel(self._axis_labels[1])
338
- ax.set_zlabel(f'Probability of {class_name}')
339
-
340
- # Set tick labels if axis values provided
341
- if self._axis_values[0]:
342
- ax.set_xticks(range(len(self._axis_values[0])))
343
- ax.set_xticklabels(self._axis_values[0])
344
- if self._axis_values[1]:
345
- ax.set_yticks(range(len(self._axis_values[1])))
346
- ax.set_yticklabels(self._axis_values[1])
347
-
348
- # Add colorbar
349
- cbar = fig.colorbar(surf, ax=ax, shrink=0.5)
350
- cbar.set_label(f'Probability of {class_name}')
351
-
352
- # Set title with filter info
353
- if title is None:
354
- title = f'3D Prediction Surface: {class_name}'
355
- if value_filter:
356
- title += f' (filtered: {value_filter[0]:.3f}-{value_filter[1]:.3f})'
357
- ax.set_title(title)
358
-
359
- return fig, ax
360
-
361
- def plot_3d_interactive(self, class_name: str = None, figsize: tuple = (12, 9)):
362
- """
363
- Create interactive 3D plot with sliders for filtering and opacity control.
364
-
365
- Perfect for Jupyter notebooks - provides sliders to explore the prediction surface.
366
-
367
- Args:
368
- class_name: Specific class to plot (default: highest probability class)
369
- figsize: Figure size
370
-
371
- Returns:
372
- Interactive widget (in Jupyter) or regular plot (elsewhere)
373
- """
374
- if self.degrees_of_freedom != 2:
375
- raise ValueError("Interactive 3D plotting only supports 2D grids")
376
-
377
- if not self._batch_processed:
378
- raise ValueError("Must call process_batch() first")
379
-
380
- # Check if we're in a Jupyter environment
381
- try:
382
- from IPython.display import display
383
- from ipywidgets import interact, FloatSlider, FloatRangeSlider, Checkbox
384
- import numpy as np
385
- jupyter_available = True
386
- except ImportError:
387
- print("⚠️ Interactive widgets require Jupyter and ipywidgets")
388
- print(" Install with: pip install ipywidgets")
389
- print(" Falling back to static 3D plot...")
390
- return self.plot_3d(class_name=class_name, figsize=figsize)
391
-
392
- if not self._prediction_matrix:
393
- raise ValueError("No predictions processed yet. Call process_batch() first.")
394
-
395
- # Choose class to plot
396
- if class_name is None:
397
- avg_probs = {}
398
- for cls, matrix in self._prediction_matrix.items():
399
- avg_probs[cls] = np.nanmean(matrix)
400
- class_name = max(avg_probs, key=avg_probs.get)
401
-
402
- matrix = self._prediction_matrix[class_name]
403
-
404
- # Get value range for sliders
405
- min_val = float(np.nanmin(matrix))
406
- max_val = float(np.nanmax(matrix))
407
- value_range = max_val - min_val
408
-
409
- print(f"🎛️ Interactive 3D Surface Explorer: {class_name}")
410
- print(f" Value range: {min_val:.4f} to {max_val:.4f}")
411
- print(" Use sliders below to filter and adjust opacity")
412
-
413
- # Create interactive plot function
414
- def update_plot(value_range=(min_val, max_val), opacity=0.8, wireframe=False):
415
- """Update the 3D plot based on slider values."""
416
- import matplotlib.pyplot as plt
417
- plt.close('all') # Close previous plots
418
-
419
- fig, ax = self.plot_3d(
420
- class_name=class_name,
421
- figsize=figsize,
422
- value_filter=value_range,
423
- opacity=opacity,
424
- show_wireframe=wireframe
425
- )
426
-
427
- # Show current filter stats
428
- filtered_matrix = matrix.copy()
429
- mask = (filtered_matrix < value_range[0]) | (filtered_matrix > value_range[1])
430
- filtered_matrix[mask] = np.nan
431
-
432
- visible_count = np.sum(~np.isnan(filtered_matrix))
433
- total_count = np.sum(~np.isnan(matrix))
434
- visible_percent = (visible_count / total_count) * 100 if total_count > 0 else 0
435
-
436
- print(f"📊 Showing {visible_count}/{total_count} points ({visible_percent:.1f}%)")
437
- plt.show()
438
-
439
- # Create interactive widgets
440
- value_slider = FloatRangeSlider(
441
- value=(min_val, max_val),
442
- min=min_val,
443
- max=max_val,
444
- step=value_range / 100,
445
- description='Value Filter:',
446
- continuous_update=False,
447
- style={'description_width': 'initial'}
448
- )
449
-
450
- opacity_slider = FloatSlider(
451
- value=0.8,
452
- min=0.1,
453
- max=1.0,
454
- step=0.1,
455
- description='Opacity:',
456
- continuous_update=False,
457
- style={'description_width': 'initial'}
458
- )
459
-
460
- wireframe_checkbox = Checkbox(
461
- value=False,
462
- description='Show Wireframe',
463
- style={'description_width': 'initial'}
464
- )
465
-
466
- # Create interactive widget
467
- return interact(
468
- update_plot,
469
- value_range=value_slider,
470
- opacity=opacity_slider,
471
- wireframe=wireframe_checkbox
472
- )
473
-
474
- def plot_1d(self, class_name: str = None, figsize: tuple = (10, 6), title: str = None):
475
- """
476
- Plot 1D line plot of prediction probabilities.
477
-
478
- Args:
479
- class_name: Specific class to plot (default: highest probability class)
480
- figsize: Figure size
481
- title: Custom title
482
- """
483
- if self.degrees_of_freedom != 1:
484
- raise ValueError("1D plotting only supports 1D grids")
485
-
486
- if not self._batch_processed:
487
- raise ValueError("Must call process_batch() first")
488
-
489
- try:
490
- import matplotlib.pyplot as plt
491
- import numpy as np
492
- except ImportError:
493
- raise ImportError("matplotlib required for plotting. Install with: pip install matplotlib")
494
-
495
- if not self._prediction_matrix:
496
- raise ValueError("No predictions processed yet. Call process_batch() first.")
497
-
498
- # Choose class to plot
499
- if class_name is None:
500
- avg_probs = {}
501
- for cls, matrix in self._prediction_matrix.items():
502
- avg_probs[cls] = np.nanmean(matrix)
503
- class_name = max(avg_probs, key=avg_probs.get)
504
-
505
- matrix = self._prediction_matrix[class_name]
506
-
507
- # Create plot
508
- fig, ax = plt.subplots(figsize=figsize)
509
-
510
- # X values
511
- x = self._axis_values[0] if self._axis_values[0] else range(len(matrix))
512
-
513
- # Plot line
514
- ax.plot(x, matrix, marker='o', linewidth=2, markersize=6)
515
-
516
- # Set labels
517
- ax.set_xlabel(self._axis_labels[0])
518
- ax.set_ylabel(f'Probability of {class_name}')
519
-
520
- # Set title
521
- if title is None:
522
- title = f'Prediction Curve: {class_name}'
523
- ax.set_title(title)
524
-
525
- ax.grid(True, alpha=0.3)
526
- plt.tight_layout()
527
-
528
- return fig, ax
529
-
530
- def get_optimal_position(self, class_name: str = None) -> tuple:
531
- """
532
- Find grid position with highest probability for a class.
533
-
534
- Args:
535
- class_name: Class to optimize for (default: highest average probability)
536
-
537
- Returns:
538
- Grid position tuple with highest probability
539
- """
540
- import numpy as np
541
-
542
- if not self._batch_processed:
543
- raise ValueError("Must call process_batch() first")
544
-
545
- if not self._prediction_matrix:
546
- raise ValueError("No predictions processed yet. Call process_batch() first.")
547
-
548
- if class_name is None:
549
- avg_probs = {}
550
- for cls, matrix in self._prediction_matrix.items():
551
- avg_probs[cls] = np.nanmean(matrix)
552
- class_name = max(avg_probs, key=avg_probs.get)
553
-
554
- matrix = self._prediction_matrix[class_name]
555
- optimal_idx = np.unravel_index(np.nanargmax(matrix), matrix.shape)
556
-
557
- return optimal_idx
558
-
559
- def get_stats(self) -> Dict[str, Any]:
560
- """Get grid statistics."""
561
- import numpy as np
562
-
563
- total_positions = int(np.prod(self.grid_shape))
564
- filled_ratio = len(self._filled_positions) / total_positions if total_positions > 0 else 0
565
-
566
- return {
567
- 'grid_shape': self.grid_shape,
568
- 'degrees_of_freedom': self.degrees_of_freedom,
569
- 'total_positions': total_positions,
570
- 'filled_positions': len(self._filled_positions),
571
- 'fill_ratio': filled_ratio,
572
- 'pending_records': len(self._pending_records),
573
- 'batch_processed': self._batch_processed,
574
- 'predictions_made': self._stats['predictions'],
575
- 'errors': self._stats['errors'],
576
- 'available_classes': list(self._prediction_matrix.keys()) if self._prediction_matrix else []
577
- }
578
-
579
- def export_data(self) -> Dict[str, Any]:
580
- """Export grid data for external analysis."""
581
- import numpy as np
582
-
583
- if not self._batch_processed:
584
- raise ValueError("Must call process_batch() first")
585
-
586
- return {
587
- 'prediction_matrices': {cls: matrix.tolist() for cls, matrix in self._prediction_matrix.items()},
588
- 'confidence_matrix': self._confidence_matrix.tolist() if self._confidence_matrix is not None else None,
589
- 'grid_shape': self.grid_shape,
590
- 'axis_labels': self._axis_labels,
591
- 'axis_values': self._axis_values,
592
- 'filled_positions': list(self._filled_positions),
593
- 'stats': self.get_stats()
594
- }
595
-
596
- def _is_resource_blocking_error(self, job: Dict[str, Any]) -> bool:
597
- """
598
- Check if a job failed due to resource blocking/conflicts.
599
-
600
- Args:
601
- job: Job information dictionary
602
-
603
- Returns:
604
- True if the job failed due to resource blocking, False otherwise
605
- """
606
- # Check for common resource blocking patterns
607
- error_indicators = [
608
- job.get('error', '').lower(),
609
- job.get('message', '').lower(),
610
- job.get('failure_reason', '').lower()
611
- ]
612
-
613
- blocking_patterns = [
614
- 'already running',
615
- 'resource conflict',
616
- 'another job is running',
617
- 'blocked by',
618
- 'queue conflict',
619
- 'job conflict',
620
- 'resource busy',
621
- 'concurrent execution not allowed'
622
- ]
623
-
624
- for indicator in error_indicators:
625
- if indicator and any(pattern in indicator for pattern in blocking_patterns):
626
- return True
627
-
628
- return False
629
-
@@ -1,10 +0,0 @@
1
- featrixsphere/__init__.py,sha256=Hq4-OHvU-90M5fpcbBjcYWoiVrE0hydodvub_Tpp4aQ,1897
2
- featrixsphere/cli.py,sha256=4Mvp8xaDHDYfZwNaic5zZOzNBhY7VEIBrAJA7XPx84A,7386
3
- featrixsphere/client.py,sha256=aj_DdAOuIR2L7FkrBeQTZuqhZzpF4DW7GYLSCKJvjs8,411229
4
- featrixsphere/client_movie_v2.py,sha256=8wm9DTClH_MUBRLKbx4N7UHO5Iy7EOs-zqpCECxY0mU,21401
5
- featrixsphere/prediction_grid.py,sha256=Thr3FZLZgIAkfOXq9Z8e4wcQ09tCN4VfCvY4PO_P8NM,25111
6
- featrixsphere-0.1.560.dist-info/METADATA,sha256=AmQE-Qa4bQ6J5Ql6lkKP2gvxUj90Mfsh-8HO6u7JiwQ,14744
7
- featrixsphere-0.1.560.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92
8
- featrixsphere-0.1.560.dist-info/entry_points.txt,sha256=QreJeYfD_VWvbEqPmMXZ3pqqlFlJ1qZb-NtqnyhEldc,51
9
- featrixsphere-0.1.560.dist-info/top_level.txt,sha256=AyN4wjfzlD0hWnDieuEHX0KckphIk_aC73XCG4df5uU,14
10
- featrixsphere-0.1.560.dist-info/RECORD,,