Engee documentation
Notebook

Engineering data and signals

In [ ]:
# import Pkg
# Pkg.add(["Statistics", "StatsBase", "StatsPlots", "CSV", "DataFrames", "Dates", "XLSX", "MAT", "WAV", "Images", "FileIO", "DSP", "FFTW", "DelimitedFiles"])

Importing libraries

We'll connect libraries for working with data, signals, and visualization. StatsBase and Statistics will provide statistical functions. CSV, XLSX, and MAT will allow you to read data from the appropriate formats. WAV is for audio files. Images - for uploading images. DSP and FFTW are for spectral analysis.

In [ ]:
using Statistics, StatsBase, StatsPlots
using CSV, DataFrames, Dates, XLSX, MAT, WAV, Images, FileIO
using DSP, FFTW, DelimitedFiles
include("media_player.jl")
Out[0]:
base64encode_image (generic function with 1 method)

Reading a CSV file with energy consumption data

Let's start with the most common engineering data format, CSV. Let's read the file with the energy consumption indicators of the steel company. The CSV.read function returns a DataFrame, a tabular structure where columns are available by name. We will immediately deduce the dimension in order to understand the scale of the data.

In [ ]:
df_energy = CSV.read("Steel_Industry.csv", DataFrame)
println("Data dimension: ", size(df_energy))
println("Column Names: ", names(df_energy))
Data dimension: (35040, 11)
Имена столбцов: ["date", "Usage_kWh", "Lagging_Current_Reactive_Power_kVarh", "Leading_Current_Reactive_Power_kVarh", "CO2_tCO2_", "Lagging_Current_Power_Factor", "Leading_Current_Power_Factor", "NSM", "WeekStatus", "Day_of_week", "Load_Type"]

Initial data inspection

The first rule of an engineer when receiving data is to look at it through his eyes. We will display the first and last rows, column types. This will help to detect problems: omissions, incorrect types, unexpected values.

In [ ]:
println("The first 10 lines:")
first(df_energy, 10)
The first 10 lines:
Out[0]:
10×11 DataFrame
RowdateUsage_kWhLagging_Current_Reactive_Power_kVarhLeading_Current_Reactive_Power_kVarhCO2_tCO2_Lagging_Current_Power_FactorLeading_Current_Power_FactorNSMWeekStatusDay_of_weekLoad_Type
String31Float64Float64Float64Float64Float64Float64Int64String7String15String15
101/01/2018 00:153.172.950.00.073.21100.0900WeekdayMondayLight_Load
201/01/2018 00:304.04.460.00.066.77100.01800WeekdayMondayLight_Load
301/01/2018 00:453.243.280.00.070.28100.02700WeekdayMondayLight_Load
401/01/2018 01:003.313.560.00.068.09100.03600WeekdayMondayLight_Load
501/01/2018 01:153.824.50.00.064.72100.04500WeekdayMondayLight_Load
601/01/2018 01:303.283.560.00.067.76100.05400WeekdayMondayLight_Load
701/01/2018 01:453.64.140.00.065.62100.06300WeekdayMondayLight_Load
801/01/2018 02:003.64.280.00.064.37100.07200WeekdayMondayLight_Load
901/01/2018 02:153.283.640.00.066.94100.08100WeekdayMondayLight_Load
1001/01/2018 02:303.784.720.00.062.51100.09000WeekdayMondayLight_Load
In [ ]:
println("\Column data types:")
[names(df_energy) eltype.(eachcol(df_energy))]
Column Data types:
Out[0]:
11×2 Matrix{Any}:
 "date"                                  String31
 "Usage_kWh"                             Float64
 "Lagging_Current_Reactive_Power_kVarh"  Float64
 "Leading_Current_Reactive_Power_kVarh"  Float64
 "CO2_tCO2_"                             Float64
 "Lagging_Current_Power_Factor"          Float64
 "Leading_Current_Power_Factor"          Float64
 "NSM"                                   Int64
 "WeekStatus"                            String7
 "Day_of_week"                           String15
 "Load_Type"                             String15

Date and time conversion

In engineering data, timestamps are often stored as strings. Converting the date column to the DateTime format. After the conversion, we can calculate the date range and the average measurement step. Add a new DateTime column to the DataFrame.

In [ ]:
df_energy.DateTime = DateTime.(df_energy.date, dateformat"dd/mm/yyyy HH:MM")
println("Range: ", minimum(df_energy.DateTime), " — ", maximum(df_energy.DateTime))

step_sec = mean([Dates.value(dt)/1000 for dt in diff(df_energy.DateTime)])
println("The middle step: ", round(step_sec, digits=2), " sec")
Range: 2018-01-01T00:00:00 — 2018-12-31T23:45:00
Average step: 897.53 sec

Visualization of a time series

A graph is the best way to understand the behavior of a system. Let's plot the energy consumption for the entire period. On the X-axis is time, on the Y - kilowatt-hours. We see cyclical patterns and outliers.

In [ ]:
plot(df_energy.DateTime, df_energy.Usage_kWh,
     xlabel="Time", ylabel="kWh",
     title="Energy consumption",
     linewidth=0.5, legend=false, size=(900, 350))
Out[0]:

Reading data from a MAT file

The MATLAB (.mat) format is a standard in engineering practice. It can store signals, matrices, and structures. Let's read the file with the acoustic signals of the bearing. The matread function returns a dictionary, where the keys are variable names and the values are matrices.

In [ ]:
подшипник = matread("Bearing.mat")
println("The keys are in the file: ", keys(подшипник))
println("The signal size is normal: ", size(подшипник["normal"]))
Ключи в файле: ["normal", "roller", "inner", "outer"]
Signal size normal: (1, 120000)

Converting MAT data to a vector

The data from the MAT file is stored as 1×N matrices. We transform them into one-dimensional vectors using the vec function. Now it's a regular Julia array of numbers that you can perform mathematical operations with.

In [ ]:
норма = vec(подшипник["normal"])
ролик = vec(подшипник["roller"])
println("Data type: ", typeof(норма))
println("Signal length: ", length(норма))
println("\The first 5 samples of the normal signal: \n", норма[1:5])
Data type: Vector{Float64}
Signal length: 120000

The first 5 samples of the normal signal: 
[0.08866153846153846, 0.05862092307692307, -0.056951999999999996, -0.05862092307692307, -0.04985907692307692]

Reading a WAV audio file

Acoustic data is often stored in audio formats. The wavread function returns an array of samples and the sampling rate. Unlike MAT, here the data is immediately represented as a vector.

In [ ]:
сигнал_wav, fs_wav = WAV.wavread("Bearing_1.wav")
println("Sampling rate: ", fs_wav, " Hz")
println("Duration: ", round(length(сигнал_wav)/fs_wav, digits=2), " sec")
Sampling rate: 10000.0 Hz
Duration: 12.0 seconds

Audio file playback in Engee

We will reproduce the acoustic signal of the bearing using the built-in audio player.

In [ ]:
media_player("$(@__DIR__)/Bearing_1.wav", mode="audio")
Подшипник_1.wav (1 of 1)

Spectral analysis via FFT

The fast Fourier transform translates the signal from the time domain to the frequency domain. It is a key tool for vibration and acoustic analysis. We center the signal, apply FFT, and take the module for the amplitude spectrum. We will plot only the first half (frequencies from 0 to Nyquist).

In [ ]:
signal = normal[1:4000] .- mean(norm[1:4000])
spectrum = abs.(fft(signal))
N = length(signal)
frequencies = (0:N÷2-1) * 10000 /N

plot(frequencies, spectrum[1:N÷2],
     xlabel="Frequency, Hz", ylabel="The amplitude",
     title="Acoustic spectrum of the bearing",
     linewidth=1, legend=false, size=(800, 350))
Out[0]:

Data compression via FFT

One of the practical tasks is data compression. Let's look at the spectrum and determine in which range the main energy of the signal is concentrated. Then we will leave only a few key frequency components - this will be a compressed representation. Instead of 4000 signal samples, you can store 20 numbers.

In [ ]:
amplitudes = spectrum[1:N÷2]
energy_in total = sum(amplitudes.^2)
cum_energy = cumsum(amplitudes.^2) / General energy

plot(frequencies, cumulation_energy,
     xlabel="Frequency, Hz", ylabel="Stored energy",
     title="Cumulative energy of the spectrum",
     linewidth=2, legend=false, size=(800, 350))
hline!([0.95], linestyle=:dash, label="95% of the energy")
Out[0]:

Selecting informative frequency bands

Let's divide the frequency range into 20 equal bands and calculate the average amplitude in each. This will give a compact representation of the signal - 20 numbers that can be stored in a table.

In [ ]:
track_strip = 20
stripes = range(0, 5000, length=col_strip+1)
sign_fft = zeros(color_strip)

for i in 1:col_strip
    mask = (frequencies .>= bands[i]) .& (frequencies .< bands[i+1])
    if sum(mask) > 0
        sign_fft[i] = mean(amplitudes[mask])
    end
end

bar(1:color_strip, sign_fft,
    xlabel="Band number", ylabel="Average amplitude",
    title="Compressed signal representation (20 bands)",
    legend=false, size=(700, 300))
Out[0]:

Reading an image

Let's read the image file. Let's display the image type and its size.

In [ ]:
изобр = Images.load("image.png")
println("Image Type: ", typeof(изобр))
println("Size: ", size(изобр))
Image type: Matrix{RGBA{N0f8}}
Size: (954, 923)

Let's display the image.

In [ ]:
the invention
Out[0]:
No description has been provided for this image

Converting an image to a numeric matrix

Convert the image into a matrix of numbers.

In [ ]:
channels = Float64.(Images.channelview(fig))
channels = permutedims(channels, (2, 3, 1))
Out[0]:
954×923×4 Array{Float64, 3}:
[:, :, 1] =
 0.996078  0.996078  0.996078  0.996078  …  0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078  …  0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078  …  0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078
 ⋮                                       ⋱  ⋮                   
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078  …  0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078  …  0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078

[:, :, 2] =
 0.996078  0.996078  0.996078  0.996078  …  0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078  …  0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078  …  0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078
 ⋮                                       ⋱  ⋮                   
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078  …  0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078  …  0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078

[:, :, 3] =
 0.996078  0.996078  0.996078  0.996078  …  0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078  …  0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078  …  0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078
 ⋮                                       ⋱  ⋮                   
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078  …  0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078  …  0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078
 0.996078  0.996078  0.996078  0.996078     0.996078  0.996078  0.996078

[:, :, 4] =
 1.0  1.0  1.0  1.0  1.0  1.0  1.0  1.0  …  1.0  1.0  1.0  1.0  1.0  1.0  1.0
 1.0  1.0  1.0  1.0  1.0  1.0  1.0  1.0     1.0  1.0  1.0  1.0  1.0  1.0  1.0
 1.0  1.0  1.0  1.0  1.0  1.0  1.0  1.0     1.0  1.0  1.0  1.0  1.0  1.0  1.0
 1.0  1.0  1.0  1.0  1.0  1.0  1.0  1.0     1.0  1.0  1.0  1.0  1.0  1.0  1.0
 1.0  1.0  1.0  1.0  1.0  1.0  1.0  1.0     1.0  1.0  1.0  1.0  1.0  1.0  1.0
 1.0  1.0  1.0  1.0  1.0  1.0  1.0  1.0  …  1.0  1.0  1.0  1.0  1.0  1.0  1.0
 1.0  1.0  1.0  1.0  1.0  1.0  1.0  1.0     1.0  1.0  1.0  1.0  1.0  1.0  1.0
 1.0  1.0  1.0  1.0  1.0  1.0  1.0  1.0     1.0  1.0  1.0  1.0  1.0  1.0  1.0
 1.0  1.0  1.0  1.0  1.0  1.0  1.0  1.0     1.0  1.0  1.0  1.0  1.0  1.0  1.0
 1.0  1.0  1.0  1.0  1.0  1.0  1.0  1.0     1.0  1.0  1.0  1.0  1.0  1.0  1.0
 1.0  1.0  1.0  1.0  1.0  1.0  1.0  1.0  …  1.0  1.0  1.0  1.0  1.0  1.0  1.0
 1.0  1.0  1.0  1.0  1.0  1.0  1.0  1.0     1.0  1.0  1.0  1.0  1.0  1.0  1.0
 1.0  1.0  1.0  1.0  1.0  1.0  1.0  1.0     1.0  1.0  1.0  1.0  1.0  1.0  1.0
 ⋮                        ⋮              ⋱                      ⋮         
 1.0  1.0  1.0  1.0  1.0  1.0  1.0  1.0     1.0  1.0  1.0  1.0  1.0  1.0  1.0
 1.0  1.0  1.0  1.0  1.0  1.0  1.0  1.0     1.0  1.0  1.0  1.0  1.0  1.0  1.0
 1.0  1.0  1.0  1.0  1.0  1.0  1.0  1.0     1.0  1.0  1.0  1.0  1.0  1.0  1.0
 1.0  1.0  1.0  1.0  1.0  1.0  1.0  1.0  …  1.0  1.0  1.0  1.0  1.0  1.0  1.0
 1.0  1.0  1.0  1.0  1.0  1.0  1.0  1.0     1.0  1.0  1.0  1.0  1.0  1.0  1.0
 1.0  1.0  1.0  1.0  1.0  1.0  1.0  1.0     1.0  1.0  1.0  1.0  1.0  1.0  1.0
 1.0  1.0  1.0  1.0  1.0  1.0  1.0  1.0     1.0  1.0  1.0  1.0  1.0  1.0  1.0
 1.0  1.0  1.0  1.0  1.0  1.0  1.0  1.0     1.0  1.0  1.0  1.0  1.0  1.0  1.0
 1.0  1.0  1.0  1.0  1.0  1.0  1.0  1.0  …  1.0  1.0  1.0  1.0  1.0  1.0  1.0
 1.0  1.0  1.0  1.0  1.0  1.0  1.0  1.0     1.0  1.0  1.0  1.0  1.0  1.0  1.0
 1.0  1.0  1.0  1.0  1.0  1.0  1.0  1.0     1.0  1.0  1.0  1.0  1.0  1.0  1.0
 1.0  1.0  1.0  1.0  1.0  1.0  1.0  1.0     1.0  1.0  1.0  1.0  1.0  1.0  1.0

The image is represented by a 954×923×4 three-dimensional array. The first two dimensions are 954 rows and 923 columns of pixels. The third dimension consists of four color channels: red, green, blue, and an alpha transparency channel. Each value ranges from 0 to 1, where for color channels 0 means no color, 1 means maximum intensity, and for the alpha channel 1 means full opacity.

Reading a text file with data

Text files are the simplest storage format. Let's read the txt file with numerical data on ambient temperature, determine the number of values, the range, and output the first 5 values.

In [ ]:
температура = vec(readdlm("температура.txt"))
println("Number of values: ", length(температура))
println("Range: ", minimum(температура), " ... ", maximum(температура), " °C")
println("The first 5 values: ", температура[1:5])
Number of values: 35040
Range: -28.9 ... 37.4 °C
The first 5 values: [-12.3, -9.8, -9.7, -10.9, -13.4]

Reading data from Excel

Excel files are widely distributed in the industry. Similarly, let's read the xlsx file with data on ambient humidity.

In [ ]:
xlsx_file = XLSX.readxlsx("влажность.xlsx")
sheet = xlsx_file[1]
# Extract the first column as a vector (skip the header)
влажность = Float64.(лист["A"][2:end])
println("Number of values: ", length(влажность),)
println("Range: ", minimum(влажность), " ... ", maximum(влажность), " %")
println("The first 5 values: ", влажность[1:5])
Number of values: 35040
Range: 32.8 ... 98.0 %
The first 5 values: [91.2, 82.8, 86.0, 88.8, 86.5]

Data Set Transformation

We transform a data set when some of the original columns are not needed, but new data from external sources needs to be added. Delete the NSM, WeekStatus, Day_of_week, and Load_Type columns, and then add the temperature and humidity columns that were loaded earlier.

In [ ]:
select!(df_energy, Not([:NSM, :WeekStatus, :Day_of_week, :Load_Type]))
println("Columns after deletion: \n\n", names(df_energy))
Columns after deletion: 

["date", "Usage_kWh", "Lagging_Current_Reactive_Power_kVarh", "Leading_Current_Reactive_Power_kVarh", "CO2_tCO2_", "Lagging_Current_Power_Factor", "Leading_Current_Power_Factor", "DateTime"]

Add previously loaded temperature and humidity variables as new columns. The number of rows must match.

In [ ]:
df_energy.Temperature_C = temperature
df_energy.Humidity_Pct = humidity
Out[0]:
35040-element Vector{Float64}:
 91.2
 82.8
 86.0
 88.8
 86.5
 89.4
 85.1
 82.5
 89.5
 92.6
 91.1
 93.7
 84.4
  ⋮
 90.2
 85.4
 83.3
 94.1
 85.3
 88.5
 90.4
 88.5
 86.8
 91.0
 91.4
 95.4

Let's display the first 10 rows of the updated dataset.

In [ ]:
println("The first 10 lines:")
first(df_energy, 10)
The first 10 lines:
Out[0]:
10×10 DataFrame
RowdateUsage_kWhLagging_Current_Reactive_Power_kVarhLeading_Current_Reactive_Power_kVarhCO2_tCO2_Lagging_Current_Power_FactorLeading_Current_Power_FactorDateTimeTemperature_CHumidity_Pct
String31Float64Float64Float64Float64Float64Float64DateTimeFloat64Float64
101/01/2018 00:153.172.950.00.073.21100.02018-01-01T00:15:00-12.391.2
201/01/2018 00:304.04.460.00.066.77100.02018-01-01T00:30:00-9.882.8
301/01/2018 00:453.243.280.00.070.28100.02018-01-01T00:45:00-9.786.0
401/01/2018 01:003.313.560.00.068.09100.02018-01-01T01:00:00-10.988.8
501/01/2018 01:153.824.50.00.064.72100.02018-01-01T01:15:00-13.486.5
601/01/2018 01:303.283.560.00.067.76100.02018-01-01T01:30:00-12.589.4
701/01/2018 01:453.64.140.00.065.62100.02018-01-01T01:45:00-14.085.1
801/01/2018 02:003.64.280.00.064.37100.02018-01-01T02:00:00-10.082.5
901/01/2018 02:153.283.640.00.066.94100.02018-01-01T02:15:00-11.489.5
1001/01/2018 02:303.784.720.00.062.51100.02018-01-01T02:30:00-10.392.6

Save the converted data set to a new CSV file. The source file Steel_Industry.csv it remains unchanged - all transformations are saved in a new file. Сталелитейные_данные.csv.

In [ ]:
CSV.write("Steel_data.csv", df_energy)
Out[0]:
"Steel_data.csv"

Converting a MAT file

The data structure in a MAT file can also be represented in different ways. Suppose we have received 4 bearing data files from the test bench:

  • H_1_0.mat – fully functional bearing;
  • B_11_1.mat – malfunction of the roller element;
  • I_1_1.mat – inner ring malfunction;
  • O_6_1.mat – malfunction of the outer ring.

But the data analysis model requires a different structure – one MAT file with four keys "normal", "roller", "inner", "outer", where:

normal – fully functional bearing;

roller – malfunction of the roller element;

inner – malfunction of the inner ring;

outer – malfunction of the outer ring.

Let's upload the first file.

In [ ]:
норм_тест = matread("H_1_0.mat")
Out[0]:
Dict{String, Any} with 1 entry:
  "H_1_0" => [-0.186744 0.078973 1819.0 400.0; 0.844698 0.078973 0.0 0.0; … ; -…

This file has a different data structure than the required one. Let's display the data.

In [ ]:
норм_тест = норм_тест["H_1_0"]
Out[0]:
420000×4 Matrix{Float64}:
 -0.186744   0.078973  1819.0  400.0
  0.844698   0.078973     0.0    0.0
  2.06954    0.078973     0.0    0.0
  3.35884    0.079631     0.0    0.0
  4.45475    0.078973     0.0    0.0
  5.77628    0.07996      0.0    0.0
  4.51921    0.080288     0.0    0.0
  1.84391    0.081275     0.0    0.0
 -1.63721    0.081275     0.0    0.0
 -4.53814    0.080617     0.0    0.0
 -5.66628    0.07996      0.0    0.0
 -7.8581     0.078316     0.0    0.0
 -8.18042    0.077658     0.0    0.0
  ⋮                            
  4.42251   -0.02985      0.0    0.0
  6.16307   -0.030508     0.0    0.0
  7.00112   -0.030837     0.0    0.0
  6.93666   -0.030837     0.0    0.0
  6.83996   -0.030508     0.0    0.0
  6.67879   -0.02985      0.0    0.0
  3.6167    -0.031166     0.0    0.0
  0.135582  -0.030837     0.0    0.0
 -1.25042   -0.028864     0.0    0.0
 -2.79758   -0.029522     0.0    0.0
 -4.05465   -0.028207     0.0    0.0
 -3.73233   -0.028864     0.0    0.0

The file has one key "H_1_0, the data in which is a matrix. We know that the acoustic data is located in the second column. We don't need any other data. Let's extract this data.

In [ ]:
norm_test = norm_test[:,2]
Out[0]:
420000-element Vector{Float64}:
  0.078973
  0.078973
  0.078973
  0.079631
  0.078973
  0.07996
  0.080288
  0.081275
  0.081275
  0.080617
  0.07996
  0.078316
  0.077658
  ⋮
 -0.02985
 -0.030508
 -0.030837
 -0.030837
 -0.030508
 -0.02985
 -0.031166
 -0.030837
 -0.028864
 -0.029522
 -0.028207
 -0.028864

Let's open the rest of the MAT files.

In [ ]:
ролик_тест = matread("B_11_1.mat")
внут_тест = matread("I_1_1.mat")
внеш_тест = matread("O_6_1.mat")
Out[0]:
Dict{String, Any} with 1 entry:
  "O_6_1" => [5.55065 0.047082 1818.0 400.0; 33.3351 0.038534 0.0 0.0; … ; 12.4…

Let's extract the matrices.

In [ ]:
ролик_тест = ролик_тест["B_11_1"]
внут_тест = внут_тест["I_1_1"]
внеш_тест = внеш_тест["O_6_1"]
Out[0]:
420000×4 Matrix{Float64}:
   5.55065    0.047082  1818.0  400.0
  33.3351     0.038534     0.0    0.0
  39.5883     0.033274     0.0    0.0
  43.843      0.038205     0.0    0.0
  52.578      0.033274     0.0    0.0
  31.6913     0.043466     0.0    0.0
   4.48698    0.030972     0.0    0.0
   6.03414    0.026698     0.0    0.0
 -22.6206     0.030315     0.0    0.0
 -23.781      0.042808     0.0    0.0
 -26.8431     0.023739     0.0    0.0
 -41.1866     0.03426      0.0    0.0
 -24.2322     0.018479     0.0    0.0
   ⋮                            
   8.90284   -0.018672     0.0    0.0
  -0.057814  -0.018343     0.0    0.0
 -13.3699    -0.017686     0.0    0.0
 -17.0121    -0.015713     0.0    0.0
 -17.6568    -0.021631     0.0    0.0
 -10.888     -0.018672     0.0    0.0
 -15.7551    -0.019987     0.0    0.0
  -2.44302   -0.013412     0.0    0.0
   8.93507   -0.009467     0.0    0.0
  24.7613    -0.00848      0.0    0.0
  12.4807    -0.016042     0.0    0.0
  15.5428    -0.012426     0.0    0.0

Next, we will extract the second column from each matrix in the same way.

In [ ]:
rolik_test = rolik_test[:,2]
intra_test = intra_test[:,2]
vnesh_test = vnesh_test[:,2]
Out[0]:
420000-element Vector{Float64}:
  0.047082
  0.038534
  0.033274
  0.038205
  0.033274
  0.043466
  0.030972
  0.026698
  0.030315
  0.042808
  0.023739
  0.03426
  0.018479
  ⋮
 -0.018672
 -0.018343
 -0.017686
 -0.015713
 -0.021631
 -0.018672
 -0.019987
 -0.013412
 -0.009467
 -0.00848
 -0.016042
 -0.012426

Now we have four vectors with acoustic data.: норм_тест ролик_тест, внут_тест, внеш_тест. They must be assembled into a single MAT file of the previously designated structure. Let's create a dictionary with the necessary keys.

In [ ]:
data = Dict(
    "normal" => норм_тест,
    "roller" => ролик_тест,
    "inner"  => внут_тест,
    "outer"  => внеш_тест)
Out[0]:
Dict{String, Vector{Float64}} with 4 entries:
  "normal" => [0.078973, 0.078973, 0.078973, 0.079631, 0.078973, 0.07996, 0.080…
  "roller" => [0.029329, 0.025055, 0.023739, 0.025383, 0.027356, 0.029657, 0.03…
  "inner"  => [0.07437, 0.083576, 0.088179, 0.088508, 0.092453, 0.092453, 0.088…
  "outer"  => [0.047082, 0.038534, 0.033274, 0.038205, 0.033274, 0.043466, 0.03…

Save this data to a new MAT file.

In [ ]:
matwrite("Bearing test.mat", данные)

Let's read the created file.

In [ ]:
matread("Bearing test.mat")
Out[0]:
Dict{String, Any} with 4 entries:
  "normal" => [0.078973, 0.078973, 0.078973, 0.079631, 0.078973, 0.07996, 0.080…
  "roller" => [0.029329, 0.025055, 0.023739, 0.025383, 0.027356, 0.029657, 0.03…
  "inner"  => [0.07437, 0.083576, 0.088179, 0.088508, 0.092453, 0.092453, 0.088…
  "outer"  => [0.047082, 0.038534, 0.033274, 0.038205, 0.033274, 0.043466, 0.03…

The structure of the created file corresponds to the required one. The data is ready for further use.