geometallurgy 0.4.9__tar.gz → 0.4.11__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.
- {geometallurgy-0.4.9 → geometallurgy-0.4.11}/PKG-INFO +1 -1
- {geometallurgy-0.4.9 → geometallurgy-0.4.11}/elphick/geomet/__init__.py +0 -1
- {geometallurgy-0.4.9 → geometallurgy-0.4.11}/elphick/geomet/base.py +166 -13
- {geometallurgy-0.4.9 → geometallurgy-0.4.11}/elphick/geomet/config/flowsheet_example_partition.yaml +1 -2
- {geometallurgy-0.4.9 → geometallurgy-0.4.11}/elphick/geomet/flowsheet/flowsheet.py +152 -47
- {geometallurgy-0.4.9 → geometallurgy-0.4.11}/elphick/geomet/flowsheet/operation.py +18 -8
- {geometallurgy-0.4.9 → geometallurgy-0.4.11}/elphick/geomet/flowsheet/stream.py +1 -7
- {geometallurgy-0.4.9 → geometallurgy-0.4.11}/elphick/geomet/interval_sample.py +97 -35
- {geometallurgy-0.4.9 → geometallurgy-0.4.11}/elphick/geomet/utils/block_model_converter.py +5 -4
- {geometallurgy-0.4.9 → geometallurgy-0.4.11}/elphick/geomet/utils/components.py +1 -1
- geometallurgy-0.4.11/elphick/geomet/utils/estimates.py +108 -0
- geometallurgy-0.4.11/elphick/geomet/utils/interp.py +193 -0
- geometallurgy-0.4.11/elphick/geomet/utils/interp2.py +134 -0
- {geometallurgy-0.4.9 → geometallurgy-0.4.11}/elphick/geomet/utils/pandas.py +23 -28
- {geometallurgy-0.4.9 → geometallurgy-0.4.11}/elphick/geomet/utils/size.py +2 -2
- {geometallurgy-0.4.9 → geometallurgy-0.4.11}/pyproject.toml +3 -2
- geometallurgy-0.4.9/elphick/geomet/utils/interp.py +0 -107
- {geometallurgy-0.4.9 → geometallurgy-0.4.11}/LICENSE +0 -0
- {geometallurgy-0.4.9 → geometallurgy-0.4.11}/README.md +0 -0
- {geometallurgy-0.4.9 → geometallurgy-0.4.11}/elphick/geomet/block_model.py +0 -0
- {geometallurgy-0.4.9 → geometallurgy-0.4.11}/elphick/geomet/config/__init__.py +0 -0
- {geometallurgy-0.4.9 → geometallurgy-0.4.11}/elphick/geomet/config/config_read.py +0 -0
- {geometallurgy-0.4.9 → geometallurgy-0.4.11}/elphick/geomet/config/flowsheet_example_simple.yaml +0 -0
- {geometallurgy-0.4.9 → geometallurgy-0.4.11}/elphick/geomet/config/mc_config.yml +0 -0
- {geometallurgy-0.4.9 → geometallurgy-0.4.11}/elphick/geomet/data/downloader.py +0 -0
- {geometallurgy-0.4.9 → geometallurgy-0.4.11}/elphick/geomet/data/register.csv +0 -0
- {geometallurgy-0.4.9 → geometallurgy-0.4.11}/elphick/geomet/datasets/__init__.py +0 -0
- {geometallurgy-0.4.9 → geometallurgy-0.4.11}/elphick/geomet/datasets/datasets.py +0 -0
- {geometallurgy-0.4.9 → geometallurgy-0.4.11}/elphick/geomet/datasets/downloader.py +0 -0
- {geometallurgy-0.4.9 → geometallurgy-0.4.11}/elphick/geomet/datasets/register.csv +0 -0
- {geometallurgy-0.4.9 → geometallurgy-0.4.11}/elphick/geomet/datasets/sample_data.py +0 -0
- {geometallurgy-0.4.9 → geometallurgy-0.4.11}/elphick/geomet/extras.py +0 -0
- {geometallurgy-0.4.9 → geometallurgy-0.4.11}/elphick/geomet/flowsheet/__init__.py +0 -0
- {geometallurgy-0.4.9 → geometallurgy-0.4.11}/elphick/geomet/flowsheet/loader.py +0 -0
- {geometallurgy-0.4.9 → geometallurgy-0.4.11}/elphick/geomet/io.py +0 -0
- {geometallurgy-0.4.9 → geometallurgy-0.4.11}/elphick/geomet/plot.py +0 -0
- {geometallurgy-0.4.9 → geometallurgy-0.4.11}/elphick/geomet/profile.py +0 -0
- {geometallurgy-0.4.9 → geometallurgy-0.4.11}/elphick/geomet/sample.py +0 -0
- {geometallurgy-0.4.9 → geometallurgy-0.4.11}/elphick/geomet/utils/__init__.py +0 -0
- {geometallurgy-0.4.9 → geometallurgy-0.4.11}/elphick/geomet/utils/amenability.py +0 -0
- {geometallurgy-0.4.9 → geometallurgy-0.4.11}/elphick/geomet/utils/data.py +0 -0
- {geometallurgy-0.4.9 → geometallurgy-0.4.11}/elphick/geomet/utils/layout.py +0 -0
- {geometallurgy-0.4.9 → geometallurgy-0.4.11}/elphick/geomet/utils/moisture.py +0 -0
- {geometallurgy-0.4.9 → geometallurgy-0.4.11}/elphick/geomet/utils/parallel.py +0 -0
- {geometallurgy-0.4.9 → geometallurgy-0.4.11}/elphick/geomet/utils/partition.py +0 -0
- {geometallurgy-0.4.9 → geometallurgy-0.4.11}/elphick/geomet/utils/sampling.py +0 -0
- {geometallurgy-0.4.9 → geometallurgy-0.4.11}/elphick/geomet/utils/timer.py +0 -0
- {geometallurgy-0.4.9 → geometallurgy-0.4.11}/elphick/geomet/utils/viz.py +0 -0
- {geometallurgy-0.4.9 → geometallurgy-0.4.11}/elphick/geomet/validate.py.hide +0 -0
|
@@ -122,7 +122,8 @@ class MassComposition(ABC):
|
|
|
122
122
|
mass_wet=self.mass_wet_var, mass_dry=self.mass_dry_var,
|
|
123
123
|
moisture_column_name=self.moisture_column,
|
|
124
124
|
component_columns=composition.columns,
|
|
125
|
-
composition_units=self.composition_units
|
|
125
|
+
composition_units=self.composition_units,
|
|
126
|
+
return_moisture=False)
|
|
126
127
|
self._logger.debug(f"Data has been set.")
|
|
127
128
|
|
|
128
129
|
else:
|
|
@@ -229,19 +230,24 @@ class MassComposition(ABC):
|
|
|
229
230
|
(self.mass_columns + [self.moisture_column] + self.composition_columns + self.supplementary_columns) if
|
|
230
231
|
col is not None]
|
|
231
232
|
|
|
232
|
-
def balance_composition(self) -> MC:
|
|
233
|
+
def balance_composition(self, epsilon: float = 1.0e-6) -> MC:
|
|
233
234
|
"""Balance the composition data
|
|
234
235
|
|
|
235
236
|
For records where the component mass exceeds the dry mass, the component masses are reduced proportionally
|
|
236
237
|
to equal the dry mass. Records where the component mass is less than the dry mass are left unchanged.
|
|
237
238
|
|
|
239
|
+
epsilon: A small float to avoid component sums marginally over 100.0
|
|
240
|
+
|
|
241
|
+
Returns:
|
|
242
|
+
The object with balanced composition.
|
|
238
243
|
"""
|
|
239
244
|
if self._mass_data is not None:
|
|
240
245
|
# calculate the ratio of the sum of the components to the dry mass
|
|
241
246
|
ratio = self._mass_data[self.composition_columns].sum(axis=1) / self._mass_data[self.mass_dry_var]
|
|
242
247
|
if ratio.max() <= 1.0:
|
|
243
248
|
return self
|
|
244
|
-
|
|
249
|
+
|
|
250
|
+
before_reduction = self._mass_data[self.composition_columns].copy()
|
|
245
251
|
# add a small value to the ratio to avoid component sums marginally over 100.0
|
|
246
252
|
ratio[ratio > 1.0] = ratio[ratio > 1.0] + epsilon
|
|
247
253
|
# to avoid reducing compliant records, clip the ratio at the lower side to 1.0
|
|
@@ -249,6 +255,19 @@ class MassComposition(ABC):
|
|
|
249
255
|
# apply the ratio to the components
|
|
250
256
|
self._mass_data[self.composition_columns] = self._mass_data[self.composition_columns].div(ratio, axis=0)
|
|
251
257
|
|
|
258
|
+
# manage the reporting
|
|
259
|
+
affected_indexes = set(
|
|
260
|
+
self._mass_data.index[np.any(before_reduction != self._mass_data[self.composition_columns], axis=1)])
|
|
261
|
+
# log the action, including the first 50 indexes affected
|
|
262
|
+
affected_indexes_list = sorted(affected_indexes)[:50]
|
|
263
|
+
|
|
264
|
+
self.aggregate = self.weight_average()
|
|
265
|
+
self.status = OutOfRangeStatus(self, self.status.ranges)
|
|
266
|
+
|
|
267
|
+
self._logger.info(f"Object {self.name} has been balanced. "
|
|
268
|
+
f"{len(affected_indexes)} records where composition has been reduced "
|
|
269
|
+
f"to conform to dry mass. "
|
|
270
|
+
f"Affected indexes (first 50): {affected_indexes_list}")
|
|
252
271
|
return self
|
|
253
272
|
|
|
254
273
|
def clip_recovery(self, other: MC, recovery_bounds: tuple[float, float] = (0.01, 0.99),
|
|
@@ -325,9 +344,12 @@ class MassComposition(ABC):
|
|
|
325
344
|
else:
|
|
326
345
|
raise ValueError(f"mass_to_adjust must be 'wet' or 'dry', not {mass_to_adjust}")
|
|
327
346
|
|
|
347
|
+
self.aggregate = self.weight_average()
|
|
348
|
+
self.status = OutOfRangeStatus(self, self.status.ranges)
|
|
349
|
+
|
|
328
350
|
return self
|
|
329
351
|
|
|
330
|
-
def clip_composition(self, ranges: Optional[dict[str, list[float]]] = None) -> MC:
|
|
352
|
+
def clip_composition(self, ranges: Optional[dict[str, list[float]]] = None, epsilon: float = 1.0e-05) -> MC:
|
|
331
353
|
"""Clip the components
|
|
332
354
|
|
|
333
355
|
Clip to the components to within the range provided or the default range for each component.
|
|
@@ -336,6 +358,7 @@ class MassComposition(ABC):
|
|
|
336
358
|
Args:
|
|
337
359
|
ranges: An optional dict defining a list of [lo, hi] floats for each component. If not provided,
|
|
338
360
|
the default range from the config file will be used.
|
|
361
|
+
epsilon: A small float to ensure the clipped values lie marginally inside the specified range.
|
|
339
362
|
|
|
340
363
|
Returns:
|
|
341
364
|
The object with clipped composition.
|
|
@@ -345,24 +368,31 @@ class MassComposition(ABC):
|
|
|
345
368
|
component_ranges: dict = self._get_component_ranges(ranges)
|
|
346
369
|
|
|
347
370
|
# define a small value to ensure the clipped values lie marginally inside the specified range.
|
|
348
|
-
epsilon: float = 0.0 # 1.0e-05
|
|
349
371
|
# clip the components
|
|
350
372
|
affected_indexes = set()
|
|
351
373
|
for component, component_range in component_ranges.items():
|
|
352
374
|
before_clip = self._mass_data[component].copy()
|
|
375
|
+
# add a small value to the range to ensure the clipped values lie marginally inside the specified range.
|
|
376
|
+
component_range = [component_range[0] + epsilon, component_range[1] - epsilon]
|
|
353
377
|
# define the component mass that aligns with the lower and upper bounds
|
|
354
378
|
component_mass_limits = self._mass_data[self.mass_dry_var].values[:, np.newaxis] * np.array(
|
|
355
379
|
component_range) / self.composition_factor
|
|
356
380
|
# apply the clip to the mass data
|
|
357
|
-
self._mass_data[component] = self._mass_data[component].clip(lower=component_mass_limits[:, 0]
|
|
358
|
-
upper=component_mass_limits[:, 1]
|
|
381
|
+
self._mass_data[component] = self._mass_data[component].clip(lower=component_mass_limits[:, 0],
|
|
382
|
+
upper=component_mass_limits[:, 1])
|
|
359
383
|
affected_indexes.update(self._mass_data.index[before_clip != self._mass_data[component]])
|
|
360
384
|
|
|
361
385
|
# log the action, including the first 50 indexes affected
|
|
362
386
|
affected_indexes_list = sorted(affected_indexes)[:50]
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
387
|
+
|
|
388
|
+
self.aggregate = self.weight_average()
|
|
389
|
+
self.status = OutOfRangeStatus(self, self.status.ranges)
|
|
390
|
+
|
|
391
|
+
if len(affected_indexes) > 0:
|
|
392
|
+
self._logger.info(f"Object {self.name} has been clipped. "
|
|
393
|
+
f"{len(affected_indexes)} records where composition has been clipped to the "
|
|
394
|
+
f"range: {component_ranges}. "
|
|
395
|
+
f"Affected indexes (first 50): {affected_indexes_list}")
|
|
366
396
|
|
|
367
397
|
return self
|
|
368
398
|
|
|
@@ -505,7 +535,8 @@ class MassComposition(ABC):
|
|
|
505
535
|
|
|
506
536
|
# Create a DataFrame from the weighted averages
|
|
507
537
|
weighted_averages_df = pd.concat([mass_sum, composition], axis=1)
|
|
508
|
-
|
|
538
|
+
|
|
539
|
+
else: # group by a variable
|
|
509
540
|
group_var: pd.Series = self._supplementary_data[group_by]
|
|
510
541
|
weighted_averages_df = self._mass_data.groupby(group_var).apply(
|
|
511
542
|
lambda x: pd.DataFrame(
|
|
@@ -600,7 +631,7 @@ class MassComposition(ABC):
|
|
|
600
631
|
non_mass_cols: list[str] = [col for col in value.columns if
|
|
601
632
|
col not in [self.mass_wet_var, self.mass_dry_var, self.moisture_var, 'h2o',
|
|
602
633
|
'H2O', 'H2O']]
|
|
603
|
-
component_cols: list[str] = get_components(value[non_mass_cols], strict=False)
|
|
634
|
+
component_cols: list[str] = get_components(value[non_mass_cols].columns, strict=False)
|
|
604
635
|
else:
|
|
605
636
|
component_cols: list[str] = self.component_vars
|
|
606
637
|
composition = value[component_cols]
|
|
@@ -632,6 +663,7 @@ class MassComposition(ABC):
|
|
|
632
663
|
self._supplementary_data.index = self._mass_data.index
|
|
633
664
|
self._supplementary_data = self._supplementary_data.loc[value.index]
|
|
634
665
|
self.aggregate = self.weight_average()
|
|
666
|
+
self.status = OutOfRangeStatus(self, self.status.ranges)
|
|
635
667
|
|
|
636
668
|
def filter_by_index(self, index: pd.Index):
|
|
637
669
|
"""Update the data by index"""
|
|
@@ -702,6 +734,10 @@ class MassComposition(ABC):
|
|
|
702
734
|
|
|
703
735
|
res: MC = self.create_congruent_object(name=name, include_mc_data=True,
|
|
704
736
|
include_supp_data=include_supplementary_data)
|
|
737
|
+
|
|
738
|
+
if set(self._mass_data.columns) != set(other._mass_data.columns):
|
|
739
|
+
raise ValueError(f"Mass data columns do not match: {set(self._mass_data.columns)} != "
|
|
740
|
+
f"{set(other._mass_data.columns)}")
|
|
705
741
|
res.update_mass_data(self._mass_data + other._mass_data)
|
|
706
742
|
|
|
707
743
|
# Ensure self and other are Stream objects
|
|
@@ -729,6 +765,11 @@ class MassComposition(ABC):
|
|
|
729
765
|
"""
|
|
730
766
|
res = self.create_congruent_object(name=name, include_mc_data=True,
|
|
731
767
|
include_supp_data=include_supplementary_data)
|
|
768
|
+
|
|
769
|
+
if set(self._mass_data.columns) != set(other._mass_data.columns):
|
|
770
|
+
raise ValueError(f"Mass data columns do not match: {set(self._mass_data.columns)} != "
|
|
771
|
+
f"{set(other._mass_data.columns)}")
|
|
772
|
+
|
|
732
773
|
res.update_mass_data(self._mass_data - other._mass_data)
|
|
733
774
|
|
|
734
775
|
# Ensure self and other are Stream objects
|
|
@@ -738,6 +779,7 @@ class MassComposition(ABC):
|
|
|
738
779
|
other: 'Stream'
|
|
739
780
|
|
|
740
781
|
# create the relationships
|
|
782
|
+
other.nodes = [self.nodes[1], other.nodes[1]]
|
|
741
783
|
res.nodes = [self.nodes[1], random_int()]
|
|
742
784
|
|
|
743
785
|
return res
|
|
@@ -890,6 +932,41 @@ class MassComposition(ABC):
|
|
|
890
932
|
|
|
891
933
|
return res
|
|
892
934
|
|
|
935
|
+
def compare(self, other: 'MassComposition', comparisons: Union[str, list[str]] = 'recovery',
|
|
936
|
+
explicit_names: bool = True) -> pd.DataFrame:
|
|
937
|
+
|
|
938
|
+
comparisons = [comparisons] if isinstance(comparisons, str) else comparisons
|
|
939
|
+
valid_comparisons: set = {'recovery', 'difference', 'divide', 'all'}
|
|
940
|
+
|
|
941
|
+
cols = [col for col in self.data.data_vars if col not in self.data.mc.mc_vars_attrs]
|
|
942
|
+
|
|
943
|
+
chunks: list[pd.DataFrame] = []
|
|
944
|
+
if 'recovery' in comparisons or comparisons == ['all']:
|
|
945
|
+
df: pd.DataFrame = self._mass_data[self.component_vars] / other._mass_data[self.component_vars]
|
|
946
|
+
if explicit_names:
|
|
947
|
+
df.columns = [f"{self.name}_{col}_{self.config['comparisons']['recovery']}_{other.name}" for col in
|
|
948
|
+
df.columns]
|
|
949
|
+
chunks.append(df)
|
|
950
|
+
if 'difference' in comparisons or comparisons == ['all']:
|
|
951
|
+
df: pd.DataFrame = self.data[cols] - other.data[cols]
|
|
952
|
+
if explicit_names:
|
|
953
|
+
df.columns = [f"{self.name}_{col}_{self.config['comparisons']['difference']}_{other.name}" for col in
|
|
954
|
+
df.columns]
|
|
955
|
+
chunks.append(df)
|
|
956
|
+
if 'divide' in comparisons or comparisons == ['all']:
|
|
957
|
+
df: pd.DataFrame = self.data[cols] / other.data[cols]
|
|
958
|
+
if explicit_names:
|
|
959
|
+
df.columns = [f"{self.name}_{col}_{self.config['comparisons']['divide']}_{other.name}" for col in
|
|
960
|
+
df.columns]
|
|
961
|
+
chunks.append(df)
|
|
962
|
+
|
|
963
|
+
if not chunks:
|
|
964
|
+
raise ValueError(f"The comparison argument is not valid: {valid_comparisons}")
|
|
965
|
+
|
|
966
|
+
res: pd.DataFrame = pd.concat(chunks, axis=1)
|
|
967
|
+
|
|
968
|
+
return res
|
|
969
|
+
|
|
893
970
|
def reset_index(self, index_name: str) -> MC:
|
|
894
971
|
res = self.create_congruent_object(name=f"{self.name} (reset_index)", include_mc_data=True,
|
|
895
972
|
include_supp_data=True)
|
|
@@ -934,7 +1011,7 @@ class OutOfRangeStatus:
|
|
|
934
1011
|
self.oor: pd.DataFrame = self._check_range()
|
|
935
1012
|
self.num_oor: int = len(self.oor)
|
|
936
1013
|
self.failing_components: Optional[list[str]] = list(
|
|
937
|
-
self.oor.dropna(axis=1).columns) if self.num_oor > 0 else None
|
|
1014
|
+
self.oor.dropna(axis=1, how='all').columns) if self.num_oor > 0 else None
|
|
938
1015
|
|
|
939
1016
|
def get_ranges(self, ranges: dict[str, list]) -> dict[str, list]:
|
|
940
1017
|
|
|
@@ -978,3 +1055,79 @@ class OutOfRangeStatus:
|
|
|
978
1055
|
if isinstance(other, OutOfRangeStatus):
|
|
979
1056
|
return self.oor.equals(other.oor)
|
|
980
1057
|
return False
|
|
1058
|
+
|
|
1059
|
+
|
|
1060
|
+
class SampleStatus:
|
|
1061
|
+
"""A class to check and report sample status in an MC object.
|
|
1062
|
+
|
|
1063
|
+
A MassComposition object (Sample, Stream, etc) can be unhealthy if:
|
|
1064
|
+
1. the total mass of components is greater than the dry mass
|
|
1065
|
+
2. any of the masses are negative
|
|
1066
|
+
3. the component values are out of range
|
|
1067
|
+
"""
|
|
1068
|
+
|
|
1069
|
+
def __init__(self, mc: 'MC', component_limits: dict):
|
|
1070
|
+
"""Initialize with an MC object."""
|
|
1071
|
+
self._logger = logging.getLogger(__name__)
|
|
1072
|
+
self.mc: 'MC' = mc
|
|
1073
|
+
self.sample_status: Optional[dict] = None
|
|
1074
|
+
self.num_samples: Optional[int] = None
|
|
1075
|
+
self.failing_samples: Optional[list[str]] = None
|
|
1076
|
+
|
|
1077
|
+
if mc.mass_data is not None:
|
|
1078
|
+
self.sample_status = self.get_sample_status(component_limits)
|
|
1079
|
+
self.num_samples = len(self.sample_status)
|
|
1080
|
+
self.failing_samples = [sample for sample, status in self.sample_status.items() if not status['ok']]
|
|
1081
|
+
|
|
1082
|
+
def get_sample_status(self, component_limits: dict) -> dict:
|
|
1083
|
+
"""Check if all records are within the constraints."""
|
|
1084
|
+
sample_status = {}
|
|
1085
|
+
if self.mc._mass_data is not None:
|
|
1086
|
+
df: pd.DataFrame = self.mc.data[self.mc.composition_columns]
|
|
1087
|
+
mass_dry = self.mc._mass_data[self.mc.mass_dry_var]
|
|
1088
|
+
|
|
1089
|
+
# Check for component limits
|
|
1090
|
+
for component, limits in component_limits.items():
|
|
1091
|
+
oor = df[(df[component] < limits[0]) | (df[component] > limits[1])]
|
|
1092
|
+
for sample in oor.index:
|
|
1093
|
+
if sample not in sample_status:
|
|
1094
|
+
sample_status[sample] = {'ok': True, 'causes': []}
|
|
1095
|
+
sample_status[sample]['ok'] = False
|
|
1096
|
+
sample_status[sample]['causes'].append(f"{component} out of range")
|
|
1097
|
+
|
|
1098
|
+
# Check if total mass of components is greater than dry mass
|
|
1099
|
+
total_component_mass = df.sum(axis=1)
|
|
1100
|
+
for sample in total_component_mass.index:
|
|
1101
|
+
if sample not in sample_status:
|
|
1102
|
+
sample_status[sample] = {'ok': True, 'causes': []}
|
|
1103
|
+
if total_component_mass[sample] > mass_dry[sample]:
|
|
1104
|
+
sample_status[sample]['ok'] = False
|
|
1105
|
+
sample_status[sample]['causes'].append("Total mass of components greater than dry mass")
|
|
1106
|
+
|
|
1107
|
+
# Check for negative masses
|
|
1108
|
+
negative_masses = df[df < 0].dropna(how='all')
|
|
1109
|
+
for sample in negative_masses.index:
|
|
1110
|
+
if sample not in sample_status:
|
|
1111
|
+
sample_status[sample] = {'ok': True, 'causes': []}
|
|
1112
|
+
sample_status[sample]['ok'] = False
|
|
1113
|
+
sample_status[sample]['causes'].append("Negative mass detected")
|
|
1114
|
+
return sample_status
|
|
1115
|
+
|
|
1116
|
+
@property
|
|
1117
|
+
def ok(self) -> bool:
|
|
1118
|
+
"""Return True if all records are within range, False otherwise."""
|
|
1119
|
+
if self.num_samples > 0:
|
|
1120
|
+
self._logger.warning(f'{self.num_samples} unhealthy samples exist.')
|
|
1121
|
+
return True if self.num_samples == 0 else False
|
|
1122
|
+
|
|
1123
|
+
def __str__(self) -> str:
|
|
1124
|
+
"""Return a string representation of the status."""
|
|
1125
|
+
res: str = f'status.ok: {self.ok}\n'
|
|
1126
|
+
res += f'num_samples: {self.num_samples}'
|
|
1127
|
+
return res
|
|
1128
|
+
|
|
1129
|
+
def __eq__(self, other: object) -> bool:
|
|
1130
|
+
"""Return True if other Status has the same out-of-range records."""
|
|
1131
|
+
if isinstance(other, SampleStatus):
|
|
1132
|
+
return self.sample_status == other.sample_status
|
|
1133
|
+
return False
|
{geometallurgy-0.4.9 → geometallurgy-0.4.11}/elphick/geomet/config/flowsheet_example_partition.yaml
RENAMED
|
@@ -23,9 +23,8 @@ FLOWSHEET:
|
|
|
23
23
|
partition:
|
|
24
24
|
module: elphick.geomet.utils.partition
|
|
25
25
|
function: napier_munn_size_1mm
|
|
26
|
+
partition_stream: Lump # the stream that the partition model defines
|
|
26
27
|
args: null # e.g. d50, ep if not defined in the (partial) function
|
|
27
|
-
output_stream: Lump
|
|
28
|
-
complement_stream: Fines
|
|
29
28
|
lump:
|
|
30
29
|
name: lump
|
|
31
30
|
fines:
|