Interval Data - Advanced

Intervals are encountered in Metallurgy, aka fractions, e.g. size fractions. In that case the typical nomenclature is size_retained, size passing, since the data originates from a sieve stack.

This example walks through unifying the intervals across samples to be represented in the same network. Consider the case where the feed, oversize and undersize from a screening operation are sampled and sieved. It is likely that the undersize size distribution will be generated with fewer sieves in the sieve stack. If this data is not unified (made consistent) the network cannot be constructed - by unifying it we can construct a network and check the magnitude of any imbalance.

import logging
from functools import partial
from pathlib import Path

import pandas as pd
import plotly

from elphick.mass_composition import MassComposition
from elphick.mass_composition.datasets.sample_data import size_by_assay
from elphick.mass_composition.flowsheet import Flowsheet
from elphick.mass_composition.utils.partition import napier_munn
logging.basicConfig(level=logging.INFO,
                    format='%(asctime)s %(levelname)s %(module)s - %(funcName)s: %(message)s',
                    datefmt='%Y-%m-%dT%H:%M:%S%z')

Create some data

We get some demo sizing data, split it with a partition, and manually drop sieves for the undersize stream.

# We create this object as 1D based on the pandas index.

df_data: pd.DataFrame = size_by_assay()
mc_feed: MassComposition = MassComposition(df_data, name='FEED')
mc_feed.data.to_dataframe()
mass_wet mass_dry H2O Fe SiO2 Al2O3
size
[0.85, 2.0) 3.3 3.3 0.0 64.15 2.04 2.68
[0.5, 0.85) 9.9 9.9 0.0 64.33 2.05 2.23
[0.15, 0.5) 26.5 26.5 0.0 64.52 1.84 2.19
[0.075, 0.15) 2.5 2.5 0.0 62.65 2.88 3.32
[0.045, 0.075) 8.8 8.8 0.0 62.81 2.12 2.25
[0.0, 0.045) 49.0 49.0 0.0 55.95 6.39 6.34


We partially initialise a partition function, and split the feed stream accordingly.

partition = partial(napier_munn, d50=0.150, ep=0.05, dim='size')
mc_oversize, mc_undersize = mc_feed.split_by_partition(partition_definition=partition, name_1='OS', name_2='US')

Drop the two size fractions from mc_fine that have near zero mass.

This simulates a common situation where fines samples will likely have fewer fractions reported in the results.

df_fine: pd.DataFrame = mc_undersize.data.to_dataframe()
df_fine = df_fine.loc[df_fine.index.left < 0.5, :]

mc_undersize.set_data(df_fine)
mc_undersize.data.to_dataframe()
mass_wet mass_dry H2O Fe SiO2 Al2O3
size
[0.15, 0.5) 1.633999 1.633999 0.0 64.52 1.84 2.19
[0.075, 0.15) 1.810638 1.810638 0.0 62.65 2.88 3.32
[0.045, 0.075) 7.769423 7.769423 0.0 62.81 2.12 2.25
[0.0, 0.045) 46.291601 46.291601 0.0 55.95 6.39 6.34


Notice that the top two fractions are now missing.

Unifying Indexes

If the dataset contains a single IntervalIndex called ‘size’ missing coarse size fractions will be added automatically.

That said, the remaining sizes must be consistent. Alignment of sizes across streams/mc objects is coming soon.

fs: Flowsheet = Flowsheet().from_streams([mc_feed, mc_oversize, mc_undersize])
fig = fs.table_plot()
fig
/home/runner/work/mass-composition/mass-composition/elphick/mass_composition/flowsheet.py:1014: FutureWarning:

The previous implementation of stack is deprecated and will be removed in a future version of pandas. See the What's New notes for pandas 2.1.0 for details. Specify future_stack=True to adopt the new implementation and silence this warning.


Troubleshooting the imbalance

So we now have our network, but it does not balance. Perhaps the fractions we removed to generate our test data contained enough mass to breach our balance threshold? Let’s dig deeper with our balance plot.

fig = fs.plot_balance(color='size')
# noinspection PyTypeChecker
plotly.io.show(fig)  # this call to show will set the thumbnail for the gallery

What is the balance threshold set at?

print('Node error tolerance:', fs.graph.nodes[1]['mc']._tolerance)
Node error tolerance: 1.1920929e-07

That plot does not reveal the problem, so we’ll resort to another report.

fs.graph.nodes[1]['mc']._balance_errors
mass_wet mass_dry Fe SiO2 Al2O3
size
[0.5, 0.85) 0.00016 0.00016 0.000103 0.000003 0.000004


Let’s change the node error tolerance.

fs.graph.nodes[1]['mc']._tolerance = 0.001
fig = fs.table_plot()
fig


TODO

Create a single imbalance report across the entire network.

Total running time of the script: ( 0 minutes 1.112 seconds)

Gallery generated by Sphinx-Gallery