27 Nov 2020

Building a Graphic User Interface for Blasting purposes - KUZ Ram Curve

"First, solve the problem. Then, write the code." – John Johnson



Programming Language: Python

Relational Database Management System: SQLite


Content

1. Problem statement
2. The solution
    2.1 Building an application
3. Application’s features
4. Future work ideas
5. Code source


1. Problem statement

When analyzing a blasting design in an open pit mining operation, we usually find explosives data saved in excel sheets that needed to be copied and pasted into a report format and then looked up.

Row explosives data
Row explosives data

Blasting engineers often use this row data to predict how fragmented the rock will be after being blasted - this is based on computing some equations, i.e., Kuz Ram model. It is most likely to find this analysis in Excel files such as the following: engineers will need to look up the explosives properties in another table and then find the best blasting parameters.

Report in an Excel file format
Report in an Excel file format

So, how can we keep the source data for a blasting design and their corresponding computations?


2. The solution

Instead of keeping using Excel files to store and perform computations, we thought about building a desktop graphical user interface (GUI) that could handle the two main processes of getting a Kuz-Ram curve (also see picture below):

  • Storing explosives data effectively
  • Compute variables dynamically based on explosives data
Prospective solution
Prospective solution

2.1 Building an application

The GUI was built with Tkinter, which offers multiple features for desktop applications.

1- Inserting, viewing, updating, and deleting data in a database table

Once we got a SQLite database (located in the Github_repo), we could perform multiple operations:

class Dabase:
    def __init__(self, db):
        """
        Connects to the dbase.
        Args:
            db (.db file): path of the db file
        """
        # Connect to db 
        self.conn = sqlite3.connect(db, check_same_thread= False)
        # Allow to execute statements
        self.c = self.conn.cursor()
        # Make sure that the table for explosives exist
        self.c.execute(
            "CREATE TABLE IF NOT EXISTS explosives \
                (id INTEGER PRIMARY KEY, name FIXED,\
                density FLOAT, VOD INTEGER,\
                     Deton_Pressure FLOAT, Energy FLOAT, Weigth_S FLOAT)"
                     )

    def insert(self, name, density, vod, detpre, energy, wes):
        """
        Insert properties for a new explosive. This comes from some input boxes
        Args:
            name (str)        : Name of the explosive
            density(float)    : Density of the ..
            vod   (float)     : Velocity of detonation
            detpre (float)    : Detonation Pressure
            energy (float)    : Energy
            wes (float)       : Weigh pressure compared to ANFO
        """
        # First one for id
        self.c.execute(
            "INSERT INTO explosives VALUES (NULL, ?, ?, ?, ?, ?, ?)", 
            (name, density, vod, detpre, energy, wes)
            )
        self.conn.commit()

    def view(self):
        """ Show row data from explosives table in the GUI"""
        self.c.execute(
            "SELECT * from explosives"
            )
        # Show them in a list - this is the best way
        # to show data in Tkinter TODO: might be another though
        rows = self.c.fetchall()
        return rows   

    def update(self, id, name, density, vod, detpre, energy, wes):
        """ Will update the database if row added from insert method"""
        self.c.execute(
            "UPDATE explosives SET name = ?, density = ?, \
                VOD = ?, Deton_Pressure =?, Energy = ?, \
                    Weigth_S = ? WHERE id = ?", 
                    (name, density, vod, detpre, energy, wes, id)
                    )
        self.conn.commit()

2- Compute all variables for Kuz-Ram model

Even though one method from the app frontend will be described here, this is not fully described here. Please, check the frontend-code for more information.

def solve_kuz_ram():
    h_column = float(textbh.get()) - float(textstem.get()) + float(textsd.get())
    # Tons/hole
    ton_hole = float(textbi.get()) * float(textsi.get()) * float(textbh.get()) * float(textrd.get())
    # Height of explosive that is in the column (this is different dfor the bottom)
    h_explosiv_column = h_column - float(texthf.get())
    # Q for bottom as well for column
    # Texthf is height of explosive at the bottom
    bottom_charge = 0.5067 * float(
        text_dens.get()
        ) * (float(hole_diameter_text.get()) **2) * float(texthf.get())
    column_charge = 0.5067 * float(
        textdec.get()
        ) * (float(hole_diameter_text.get()) **2) * h_explosiv_column
    subdrilling_charge = 0.5067 * text_dens.get() * (
        float(hole_diameter_text.get()) **2
        ) * float(textsd.get())
    # total Q, stemming is included
    total_charge = bottom_charge + column_charge
    # total Q, stemming is not included
    total_charge_nostem = total_charge - subdrilling_charge
    # WS of the whole hole
    total_weight_strenght = 100*(
        float(textweb.get()) * (bottom_charge - subdrilling_charge) + float(textwec.get()) * column_charge
        )/(bottom_charge + column_charge - subdrilling_charge)
    # Power factor, which is in gr/ton
    power_factor = total_charge * 1000 / ton_hole
    # 50 prob which is in mm
    # textrf is rockfactor
    # textrd is rockdensity
    d_50 = float(textrf.get()) * 10 * (
        (ton_hole /(float(textrd.get()) * total_charge)
        )**0.8
        ) * (total_charge **(1/6)) * ((115/total_weight_strenght) ** 0.633)
    # Uniformity index
    if pattern_text.get() == "Staggered":
        pattern_value = 1.1
    else:
        pattern_value = 1
    uniform_index = pattern_value * (
        (
            h_column - float(textsd.get())
        )/float(textbh.get()) * (
            2.2 - 14 * float(textbi.get())/(float(hole_diameter_text.get()) * 25.4)
            ) *(
                (1 + float(textsi.get())/float(textbi.get()))/2
                ) ** 0.5 * (1 - (float(textdd.get())/float(textbi.get()))) * (
                    abs(bottom_charge - column_charge) / (bottom_charge+column_charge) + 0.1
                    ) ** 0.1
                    )
    uniform_index = round(uniform_index, 2)
    #Particular size
    particular_size = d_50 / (0.693 ** (1/uniform_index))
    particular_size = round(particular_size, 0)

3. Application’s features

There are two main feature in this application:

  • Handling data in the SQLite database
Databases tab - GUI
Databases tab - GUI
  • Getting the Kuz and Ram Curve
Estimation tab - GUI
Estimation tab - GUI

4. Future work ideas

  • Build the rock parameters tab . Even though it might be just a number, it would be easier to replicate the process of getting it.
  • Research on how to show the explosives data in a table format.
  • Get a binary file to execute the scripts. Might be easier to download and run the app with one click.

5. Code source


Tags:
0 comments