Compare commits
18 Commits
main
...
feat/90-fe
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4b0819f94e | ||
|
|
f5dada1b9c | ||
|
|
37c9a0765a | ||
|
|
8656289a1c | ||
|
|
15fe8339ec | ||
|
|
44210ef372 | ||
|
|
9192d4c81c | ||
|
|
0373743ca7 | ||
|
|
49d6395e6f | ||
|
|
bf9cca2d90 | ||
|
|
08420296e6 | ||
|
|
1540213eec | ||
|
|
6fd4b7465e | ||
|
|
85a0aebf36 | ||
|
|
8d1edfdbf7 | ||
|
|
ff862d9467 | ||
|
|
dfb64db1d8 | ||
|
|
3e3de577ba |
52
.github/workflows/latex-lint.yml
vendored
52
.github/workflows/latex-lint.yml
vendored
@@ -1,52 +0,0 @@
|
|||||||
name: LaTeX Lint
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
- dev
|
|
||||||
paths:
|
|
||||||
- 'latex/**/*.tex'
|
|
||||||
- 'latex/main.tex'
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
lint:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Install chktex
|
|
||||||
run: |
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install -y chktex
|
|
||||||
|
|
||||||
- name: Run chktex inside latex/
|
|
||||||
working-directory: latex
|
|
||||||
run: |
|
|
||||||
TEX_FILES=$(find . -type f -name "*.tex")
|
|
||||||
if [ -z "$TEX_FILES" ]; then
|
|
||||||
echo "No .tex files found in latex/. Skipping lint."
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "🔍 Linting .tex files with chktex..."
|
|
||||||
FAIL=0
|
|
||||||
|
|
||||||
for f in $TEX_FILES; do
|
|
||||||
echo "▶ Checking $f"
|
|
||||||
# Run chktex and show output; capture error status
|
|
||||||
if ! chktex "$f"; then
|
|
||||||
echo "::warning file=$f::ChkTeX found issues in $f"
|
|
||||||
FAIL=1
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ $FAIL -ne 0 ]; then
|
|
||||||
echo "::error::❌ Lint errors or warnings were found in one or more .tex files above."
|
|
||||||
exit 1
|
|
||||||
else
|
|
||||||
echo "✅ All files passed chktex lint."
|
|
||||||
fi
|
|
||||||
102
.github/workflows/latexdiff.yml
vendored
102
.github/workflows/latexdiff.yml
vendored
@@ -1,102 +0,0 @@
|
|||||||
name: LaTeX Diff
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
base_branch:
|
|
||||||
description: 'Base branch (older version)'
|
|
||||||
required: true
|
|
||||||
compare_branch:
|
|
||||||
description: 'Compare branch (new version)'
|
|
||||||
required: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
latexdiff:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
container:
|
|
||||||
image: ghcr.io/xu-cheng/texlive-full:latest
|
|
||||||
options: --user root
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Install latexpand (Perl script)
|
|
||||||
run: |
|
|
||||||
tlmgr init-usertree
|
|
||||||
tlmgr install latexpand
|
|
||||||
|
|
||||||
- name: Checkout base branch
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
ref: ${{ github.event.inputs.base_branch }}
|
|
||||||
path: base
|
|
||||||
|
|
||||||
- name: Checkout compare branch
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
ref: ${{ github.event.inputs.compare_branch }}
|
|
||||||
path: compare
|
|
||||||
|
|
||||||
|
|
||||||
- name: Create output folder
|
|
||||||
run: mkdir -p diff_output
|
|
||||||
|
|
||||||
- name: Flatten base/main.tex (with latexpand)
|
|
||||||
run: |
|
|
||||||
cd base/latex
|
|
||||||
echo "📂 Listing files in base/latex:"
|
|
||||||
ls -R
|
|
||||||
echo "🔄 Flattening with latexpand..."
|
|
||||||
latexpand --verbose --keep-comments --output=../../diff_output/base_flat.tex main.tex
|
|
||||||
echo "✅ Preview of base_flat.tex:"
|
|
||||||
head -n 50 ../../diff_output/base_flat.tex
|
|
||||||
|
|
||||||
|
|
||||||
- name: Flatten compare/main.tex (with latexpand)
|
|
||||||
run: |
|
|
||||||
cd compare/latex
|
|
||||||
echo "📂 Listing files in compare/latex:"
|
|
||||||
ls -R
|
|
||||||
echo "🔄 Flattening with latexpand..."
|
|
||||||
latexpand --verbose --keep-comments --output=../../diff_output/compare_flat.tex main.tex
|
|
||||||
echo "✅ Preview of compare_flat.tex:"
|
|
||||||
head -n 50 ../../diff_output/compare_flat.tex
|
|
||||||
|
|
||||||
- name: Generate diff.tex using latexdiff
|
|
||||||
run: |
|
|
||||||
latexdiff diff_output/base_flat.tex diff_output/compare_flat.tex > diff_output/diff.tex
|
|
||||||
|
|
||||||
- name: Copy thesis.cls to diff_output
|
|
||||||
run: cp compare/latex/thesis.cls diff_output/
|
|
||||||
|
|
||||||
- name: Copy chapters/img into diff_output
|
|
||||||
run: |
|
|
||||||
# Create the same chapters/img path inside diff_output
|
|
||||||
mkdir -p diff_output/chapters/img
|
|
||||||
# Copy all images from compare branch into diff_output
|
|
||||||
cp -R compare/latex/chapters/img/* diff_output/chapters/img/
|
|
||||||
|
|
||||||
- name: Copy .bib files into diff_output
|
|
||||||
run: |
|
|
||||||
mkdir -p diff_output
|
|
||||||
cp compare/latex/*.bib diff_output/
|
|
||||||
|
|
||||||
- name: Override “\input{preamble/fonts}” in diff.tex
|
|
||||||
run: |
|
|
||||||
sed -i "/\\input{preamble\/fonts}/c % — replaced by CI: use TeX Gyre fonts instead of Times New Roman\/Arial\n\\\setmainfont{TeX Gyre Termes}\n\\\setsansfont{TeX Gyre Heros}\n\\\setmonofont{TeX Gyre Cursor}" diff_output/diff.tex
|
|
||||||
|
|
||||||
- name: Print preview of diff.tex (after font override)
|
|
||||||
run: |
|
|
||||||
echo "📄 Preview of diff_output/diff.tex after font override:"
|
|
||||||
head -n 50 diff_output/diff.tex
|
|
||||||
|
|
||||||
- name: Compile diff.tex to PDF
|
|
||||||
working-directory: diff_output
|
|
||||||
continue-on-error: true
|
|
||||||
run: |
|
|
||||||
xelatex -interaction=nonstopmode diff.tex
|
|
||||||
xelatex -interaction=nonstopmode diff.tex
|
|
||||||
|
|
||||||
- name: Upload diff output files
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: latex-diff-output
|
|
||||||
path: diff_output/
|
|
||||||
29
.github/workflows/latexmk.yml
vendored
29
.github/workflows/latexmk.yml
vendored
@@ -1,29 +0,0 @@
|
|||||||
name: Render XeLaTeX on PR to dev
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- dev
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-pdf:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Compile XeLaTeX
|
|
||||||
uses: dante-ev/latex-action@2021-A
|
|
||||||
with:
|
|
||||||
root_file: main.tex
|
|
||||||
working_directory: latex
|
|
||||||
compiler: xelatex
|
|
||||||
args: -interaction=nonstopmode -halt-on-error -file-line-error
|
|
||||||
extra_system_packages: "fonts-freefont-otf"
|
|
||||||
|
|
||||||
- name: Upload compiled PDF
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: compiled-pdf
|
|
||||||
path: latex/main.pdf
|
|
||||||
5
.vscode/settings.json
vendored
5
.vscode/settings.json
vendored
@@ -1,4 +1,7 @@
|
|||||||
{
|
{
|
||||||
"python.analysis.extraPaths": ["./code/src/features"],
|
"python.analysis.extraPaths": [
|
||||||
|
"./code/src/features",
|
||||||
|
"${workspaceFolder}/code/src"
|
||||||
|
],
|
||||||
"jupyter.notebookFileRoot": "${workspaceFolder}/code"
|
"jupyter.notebookFileRoot": "${workspaceFolder}/code"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,14 +4,20 @@ This repository contains the work related to my thesis, which focuses on damage
|
|||||||
|
|
||||||
**Note:** This repository does not contain the secondary data used in the analysis. The code is designed to work with data from the [QUGS (Qatar University Grandstand Simulator)](https://www.structuralvibration.com/benchmark/qugs/) dataset, which is not included here.
|
**Note:** This repository does not contain the secondary data used in the analysis. The code is designed to work with data from the [QUGS (Qatar University Grandstand Simulator)](https://www.structuralvibration.com/benchmark/qugs/) dataset, which is not included here.
|
||||||
|
|
||||||
|
The repository is private and access is restricted only to those who have been given explicit permission by the owner. Access is provided solely for the purpose of brief review or seeking technical guidance.
|
||||||
|
|
||||||
## Restrictions
|
## Restrictions
|
||||||
|
|
||||||
- **No Derivative Works or Cloning:** Any form of copying, cloning, or creating derivative works based on this repository is strictly prohibited.
|
- **No Derivative Works or Cloning:** Any form of copying, cloning, or creating derivative works based on this repository is strictly prohibited.
|
||||||
|
- **Limited Access:** Use beyond brief review or collaboration is not allowed without prior permission from the owner.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
All contents of this repository, including the thesis idea, code, and associated data, are copyrighted © 2024 by Rifqi Panuluh. Unauthorized use or duplication is prohibited.
|
||||||
|
|
||||||
[LICENSE](https://github.com/nuluh/thesis?tab=License-1-ov-file#readme)
|
[LICENSE](https://github.com/nuluh/thesis?tab=License-1-ov-file#readme)
|
||||||
|
|
||||||
## How to Run `stft.ipynb`
|
## How to Run `stft.ipynb`
|
||||||
|
|
||||||
1. run `pip install -e .` in root project first
|
1. run `pip install -e .` in root project first
|
||||||
|
|
||||||
2. run the notebook
|
2. run the notebook
|
||||||
@@ -17,8 +17,8 @@
|
|||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
"source": [
|
"source": [
|
||||||
"sensor1 = pd.read_csv('D:/thesis/data/converted/raw/DAMAGE_1/DAMAGE_1_TEST1_01.csv',sep=',')\n",
|
"sensor1 = pd.read_csv('D:/thesis/data/converted/raw/DAMAGE_1/DAMAGE_0_TEST1_01.csv',sep=',')\n",
|
||||||
"sensor2 = pd.read_csv('D:/thesis/data/converted/raw/DAMAGE_1/DAMAGE_1_TEST1_02.csv',sep=',')"
|
"sensor2 = pd.read_csv('D:/thesis/data/converted/raw/DAMAGE_1/DAMAGE_0_TEST1_02.csv',sep=',')"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -101,13 +101,16 @@
|
|||||||
"source": [
|
"source": [
|
||||||
"# Combined Plot for sensor 1 and sensor 2 from data1 file in which motor is operated at 800 rpm\n",
|
"# Combined Plot for sensor 1 and sensor 2 from data1 file in which motor is operated at 800 rpm\n",
|
||||||
"\n",
|
"\n",
|
||||||
"plt.plot(df1['s2'], label='sensor 2')\n",
|
"plt.plot(df1['s2'], label='Sensor 1', color='C1', alpha=0.6)\n",
|
||||||
"plt.plot(df1['s1'], label='sensor 1', alpha=0.5)\n",
|
"plt.plot(df1['s1'], label='Sensor 2', color='C0', alpha=0.6)\n",
|
||||||
"plt.xlabel(\"Number of samples\")\n",
|
"plt.xlabel(\"Number of samples\")\n",
|
||||||
"plt.ylabel(\"Amplitude\")\n",
|
"plt.ylabel(\"Amplitude\")\n",
|
||||||
"plt.title(\"Raw vibration signal\")\n",
|
"plt.title(\"Raw vibration signal\")\n",
|
||||||
"plt.ylim(-7.5, 5)\n",
|
"plt.ylim(-7.5, 5)\n",
|
||||||
"plt.legend()\n",
|
"plt.legend()\n",
|
||||||
|
"plt.locator_params(axis='x', nbins=8)\n",
|
||||||
|
"plt.ylim(-1, 1) # Adjust range as needed\n",
|
||||||
|
"plt.grid(True, linestyle='--', alpha=0.5)\n",
|
||||||
"plt.show()"
|
"plt.show()"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -334,8 +337,44 @@
|
|||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
"source": [
|
"source": [
|
||||||
"len(ready_data1a)\n",
|
"import numpy as np\n",
|
||||||
"# plt.pcolormesh(ready_data1[0])"
|
"import matplotlib.pyplot as plt\n",
|
||||||
|
"from mpl_toolkits.mplot3d import Axes3D\n",
|
||||||
|
"\n",
|
||||||
|
"# Assuming ready_data1a[0] is a DataFrame or 2D array\n",
|
||||||
|
"spectrogram_data = ready_data1a[0].values # Convert to NumPy array if it's a DataFrame\n",
|
||||||
|
"\n",
|
||||||
|
"# Get the dimensions of the spectrogram\n",
|
||||||
|
"num_frequencies, num_time_frames = spectrogram_data.shape\n",
|
||||||
|
"\n",
|
||||||
|
"# Create frequency and time arrays\n",
|
||||||
|
"frequencies = np.arange(num_frequencies) # Replace with actual frequency values if available\n",
|
||||||
|
"time_frames = np.arange(num_time_frames) # Replace with actual time values if available\n",
|
||||||
|
"\n",
|
||||||
|
"# Create a meshgrid for plotting\n",
|
||||||
|
"T, F = np.meshgrid(time_frames, frequencies)\n",
|
||||||
|
"\n",
|
||||||
|
"# Create a 3D plot\n",
|
||||||
|
"fig = plt.figure(figsize=(12, 8))\n",
|
||||||
|
"ax = fig.add_subplot(111, projection='3d')\n",
|
||||||
|
"\n",
|
||||||
|
"# Plot the surface\n",
|
||||||
|
"surf = ax.plot_surface(T, F, spectrogram_data, cmap='bwr', edgecolor='none')\n",
|
||||||
|
"\n",
|
||||||
|
"# Add labels and a color bar\n",
|
||||||
|
"ax.set_xlabel('Time Frames')\n",
|
||||||
|
"ax.set_ylabel('Frequency [Hz]')\n",
|
||||||
|
"ax.set_zlabel('Magnitude')\n",
|
||||||
|
"ax.set_title('3D Spectrogram')\n",
|
||||||
|
"# Resize the z-axis (shrink it)\n",
|
||||||
|
"z_min, z_max = 0, 0.1 # Replace with your desired range\n",
|
||||||
|
"ax.set_zlim(z_min, z_max)\n",
|
||||||
|
"ax.get_proj = lambda: np.dot(Axes3D.get_proj(ax), np.diag([1, 1, 0.5, 1])) # Shrink z-axis by 50%\n",
|
||||||
|
"ax.set_facecolor('white')\n",
|
||||||
|
"fig.colorbar(surf, ax=ax, shrink=0.5, aspect=10)\n",
|
||||||
|
"\n",
|
||||||
|
"# Show the plot\n",
|
||||||
|
"plt.show()"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -344,12 +383,32 @@
|
|||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
"source": [
|
"source": [
|
||||||
|
"from cmcrameri import cm\n",
|
||||||
|
"# Create a figure and subplots\n",
|
||||||
|
"fig, axes = plt.subplots(2, 3, figsize=(15, 8), sharex=True, sharey=True)\n",
|
||||||
|
"\n",
|
||||||
|
"# Flatten the axes array for easier iteration\n",
|
||||||
|
"axes = axes.flatten()\n",
|
||||||
|
"\n",
|
||||||
|
"# Loop through each subplot and plot the data\n",
|
||||||
"for i in range(6):\n",
|
"for i in range(6):\n",
|
||||||
" plt.pcolormesh(ready_data1a[i])\n",
|
" pcm = axes[i].pcolormesh(ready_data1a[i].transpose(), cmap='bwr', vmax=0.03, vmin=0.0)\n",
|
||||||
" plt.title(f'STFT Magnitude for case {i} sensor 1')\n",
|
" axes[i].set_title(f'Case {i} Sensor A', fontsize=12)\n",
|
||||||
" plt.xlabel(f'Frequency [Hz]')\n",
|
"\n",
|
||||||
" plt.ylabel(f'Time [sec]')\n",
|
"# Add a single color bar for all subplots\n",
|
||||||
" plt.show()"
|
"# Use the first `pcolormesh` object (or any valid one) for the color bar\n",
|
||||||
|
"cbar = fig.colorbar(pcm, ax=axes, orientation='vertical')\n",
|
||||||
|
"# cbar.set_label('Magnitude')\n",
|
||||||
|
"\n",
|
||||||
|
"# Set shared labels\n",
|
||||||
|
"fig.text(0.5, 0.04, 'Time Frames', ha='center', fontsize=12)\n",
|
||||||
|
"fig.text(0.04, 0.5, 'Frequency [Hz]', va='center', rotation='vertical', fontsize=12)\n",
|
||||||
|
"\n",
|
||||||
|
"# Adjust layout\n",
|
||||||
|
"# plt.tight_layout(rect=[0.05, 0.05, 1, 1]) # Leave space for shared labels\n",
|
||||||
|
"plt.subplots_adjust(left=0.1, right=0.75, top=0.9, bottom=0.1, wspace=0.2, hspace=0.2)\n",
|
||||||
|
"\n",
|
||||||
|
"plt.show()"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -535,8 +594,8 @@
|
|||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
"source": [
|
"source": [
|
||||||
"# len(y_data[0])\n",
|
"len(y_data[0])\n",
|
||||||
"y_data"
|
"# y_data"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -574,6 +633,16 @@
|
|||||||
"X2a, y = create_ready_data('D:/thesis/data/converted/raw/sensor2')"
|
"X2a, y = create_ready_data('D:/thesis/data/converted/raw/sensor2')"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"X1a.iloc[-1,:]\n",
|
||||||
|
"# y[2565]"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": null,
|
"execution_count": null,
|
||||||
@@ -619,137 +688,24 @@
|
|||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
"source": [
|
"source": [
|
||||||
"accuracies1 = []\n",
|
"from src.ml.model_selection import train_and_evaluate_model\n",
|
||||||
"accuracies2 = []\n",
|
"from sklearn.svm import SVC\n",
|
||||||
|
"# Define models for sensor1\n",
|
||||||
|
"models_sensor1 = {\n",
|
||||||
|
" # \"Random Forest\": RandomForestClassifier(),\n",
|
||||||
|
" # \"Bagged Trees\": BaggingClassifier(estimator=DecisionTreeClassifier(), n_estimators=10),\n",
|
||||||
|
" # \"Decision Tree\": DecisionTreeClassifier(),\n",
|
||||||
|
" # \"KNN\": KNeighborsClassifier(),\n",
|
||||||
|
" # \"LDA\": LinearDiscriminantAnalysis(),\n",
|
||||||
|
" \"SVM\": SVC(),\n",
|
||||||
|
" # \"XGBoost\": XGBClassifier()\n",
|
||||||
|
"}\n",
|
||||||
"\n",
|
"\n",
|
||||||
"\n",
|
"results_sensor1 = []\n",
|
||||||
"# 1. Random Forest\n",
|
"for name, model in models_sensor1.items():\n",
|
||||||
"rf_model1 = RandomForestClassifier()\n",
|
" res = train_and_evaluate_model(model, name, \"sensor1\", x_train1, y_train, x_test1, y_test, export='D:/thesis/models/sensor1')\n",
|
||||||
"rf_model1.fit(x_train1, y_train)\n",
|
" results_sensor1.append(res)\n",
|
||||||
"rf_pred1 = rf_model1.predict(x_test1)\n",
|
" print(f\"{name} on sensor1: Accuracy = {res['accuracy']:.2f}%\")\n"
|
||||||
"acc1 = accuracy_score(y_test, rf_pred1) * 100\n",
|
|
||||||
"accuracies1.append(acc1)\n",
|
|
||||||
"# format with color coded if acc1 > 90\n",
|
|
||||||
"acc1 = f\"\\033[92m{acc1:.2f}\\033[00m\" if acc1 > 90 else f\"{acc1:.2f}\"\n",
|
|
||||||
"print(\"Random Forest Accuracy for sensor 1:\", acc1)\n",
|
|
||||||
"rf_model2 = RandomForestClassifier()\n",
|
|
||||||
"rf_model2.fit(x_train2, y_train)\n",
|
|
||||||
"rf_pred2 = rf_model2.predict(x_test2)\n",
|
|
||||||
"acc2 = accuracy_score(y_test, rf_pred2) * 100\n",
|
|
||||||
"accuracies2.append(acc2)\n",
|
|
||||||
"# format with color coded if acc2 > 90\n",
|
|
||||||
"acc2 = f\"\\033[92m{acc2:.2f}\\033[00m\" if acc2 > 90 else f\"{acc2:.2f}\"\n",
|
|
||||||
"print(\"Random Forest Accuracy for sensor 2:\", acc2)\n",
|
|
||||||
"# print(rf_pred)\n",
|
|
||||||
"# print(y_test)\n",
|
|
||||||
"\n",
|
|
||||||
"# 2. Bagged Trees\n",
|
|
||||||
"bagged_model1 = BaggingClassifier(estimator=DecisionTreeClassifier(), n_estimators=10)\n",
|
|
||||||
"bagged_model1.fit(x_train1, y_train)\n",
|
|
||||||
"bagged_pred1 = bagged_model1.predict(x_test1)\n",
|
|
||||||
"acc1 = accuracy_score(y_test, bagged_pred1) * 100\n",
|
|
||||||
"accuracies1.append(acc1)\n",
|
|
||||||
"# format with color coded if acc1 > 90\n",
|
|
||||||
"acc1 = f\"\\033[92m{acc1:.2f}\\033[00m\" if acc1 > 90 else f\"{acc1:.2f}\"\n",
|
|
||||||
"print(\"Bagged Trees Accuracy for sensor 1:\", acc1)\n",
|
|
||||||
"bagged_model2 = BaggingClassifier(estimator=DecisionTreeClassifier(), n_estimators=10)\n",
|
|
||||||
"bagged_model2.fit(x_train2, y_train)\n",
|
|
||||||
"bagged_pred2 = bagged_model2.predict(x_test2)\n",
|
|
||||||
"acc2 = accuracy_score(y_test, bagged_pred2) * 100\n",
|
|
||||||
"accuracies2.append(acc2)\n",
|
|
||||||
"# format with color coded if acc2 > 90\n",
|
|
||||||
"acc2 = f\"\\033[92m{acc2:.2f}\\033[00m\" if acc2 > 90 else f\"{acc2:.2f}\"\n",
|
|
||||||
"print(\"Bagged Trees Accuracy for sensor 2:\", acc2)\n",
|
|
||||||
"\n",
|
|
||||||
"# 3. Decision Tree\n",
|
|
||||||
"dt_model = DecisionTreeClassifier()\n",
|
|
||||||
"dt_model.fit(x_train1, y_train)\n",
|
|
||||||
"dt_pred1 = dt_model.predict(x_test1)\n",
|
|
||||||
"acc1 = accuracy_score(y_test, dt_pred1) * 100\n",
|
|
||||||
"accuracies1.append(acc1)\n",
|
|
||||||
"# format with color coded if acc1 > 90\n",
|
|
||||||
"acc1 = f\"\\033[92m{acc1:.2f}\\033[00m\" if acc1 > 90 else f\"{acc1:.2f}\"\n",
|
|
||||||
"print(\"Decision Tree Accuracy for sensor 1:\", acc1)\n",
|
|
||||||
"dt_model2 = DecisionTreeClassifier()\n",
|
|
||||||
"dt_model2.fit(x_train2, y_train)\n",
|
|
||||||
"dt_pred2 = dt_model2.predict(x_test2)\n",
|
|
||||||
"acc2 = accuracy_score(y_test, dt_pred2) * 100\n",
|
|
||||||
"accuracies2.append(acc2)\n",
|
|
||||||
"# format with color coded if acc2 > 90\n",
|
|
||||||
"acc2 = f\"\\033[92m{acc2:.2f}\\033[00m\" if acc2 > 90 else f\"{acc2:.2f}\"\n",
|
|
||||||
"print(\"Decision Tree Accuracy for sensor 2:\", acc2)\n",
|
|
||||||
"\n",
|
|
||||||
"# 4. KNeighbors\n",
|
|
||||||
"knn_model = KNeighborsClassifier()\n",
|
|
||||||
"knn_model.fit(x_train1, y_train)\n",
|
|
||||||
"knn_pred1 = knn_model.predict(x_test1)\n",
|
|
||||||
"acc1 = accuracy_score(y_test, knn_pred1) * 100\n",
|
|
||||||
"accuracies1.append(acc1)\n",
|
|
||||||
"# format with color coded if acc1 > 90\n",
|
|
||||||
"acc1 = f\"\\033[92m{acc1:.2f}\\033[00m\" if acc1 > 90 else f\"{acc1:.2f}\"\n",
|
|
||||||
"print(\"KNeighbors Accuracy for sensor 1:\", acc1)\n",
|
|
||||||
"knn_model2 = KNeighborsClassifier()\n",
|
|
||||||
"knn_model2.fit(x_train2, y_train)\n",
|
|
||||||
"knn_pred2 = knn_model2.predict(x_test2)\n",
|
|
||||||
"acc2 = accuracy_score(y_test, knn_pred2) * 100\n",
|
|
||||||
"accuracies2.append(acc2)\n",
|
|
||||||
"# format with color coded if acc2 > 90\n",
|
|
||||||
"acc2 = f\"\\033[92m{acc2:.2f}\\033[00m\" if acc2 > 90 else f\"{acc2:.2f}\"\n",
|
|
||||||
"print(\"KNeighbors Accuracy for sensor 2:\", acc2)\n",
|
|
||||||
"\n",
|
|
||||||
"# 5. Linear Discriminant Analysis\n",
|
|
||||||
"lda_model = LinearDiscriminantAnalysis()\n",
|
|
||||||
"lda_model.fit(x_train1, y_train)\n",
|
|
||||||
"lda_pred1 = lda_model.predict(x_test1)\n",
|
|
||||||
"acc1 = accuracy_score(y_test, lda_pred1) * 100\n",
|
|
||||||
"accuracies1.append(acc1)\n",
|
|
||||||
"# format with color coded if acc1 > 90\n",
|
|
||||||
"acc1 = f\"\\033[92m{acc1:.2f}\\033[00m\" if acc1 > 90 else f\"{acc1:.2f}\"\n",
|
|
||||||
"print(\"Linear Discriminant Analysis Accuracy for sensor 1:\", acc1)\n",
|
|
||||||
"lda_model2 = LinearDiscriminantAnalysis()\n",
|
|
||||||
"lda_model2.fit(x_train2, y_train)\n",
|
|
||||||
"lda_pred2 = lda_model2.predict(x_test2)\n",
|
|
||||||
"acc2 = accuracy_score(y_test, lda_pred2) * 100\n",
|
|
||||||
"accuracies2.append(acc2)\n",
|
|
||||||
"# format with color coded if acc2 > 90\n",
|
|
||||||
"acc2 = f\"\\033[92m{acc2:.2f}\\033[00m\" if acc2 > 90 else f\"{acc2:.2f}\"\n",
|
|
||||||
"print(\"Linear Discriminant Analysis Accuracy for sensor 2:\", acc2)\n",
|
|
||||||
"\n",
|
|
||||||
"# 6. Support Vector Machine\n",
|
|
||||||
"svm_model = SVC()\n",
|
|
||||||
"svm_model.fit(x_train1, y_train)\n",
|
|
||||||
"svm_pred1 = svm_model.predict(x_test1)\n",
|
|
||||||
"acc1 = accuracy_score(y_test, svm_pred1) * 100\n",
|
|
||||||
"accuracies1.append(acc1)\n",
|
|
||||||
"# format with color coded if acc1 > 90\n",
|
|
||||||
"acc1 = f\"\\033[92m{acc1:.2f}\\033[00m\" if acc1 > 90 else f\"{acc1:.2f}\"\n",
|
|
||||||
"print(\"Support Vector Machine Accuracy for sensor 1:\", acc1)\n",
|
|
||||||
"svm_model2 = SVC()\n",
|
|
||||||
"svm_model2.fit(x_train2, y_train)\n",
|
|
||||||
"svm_pred2 = svm_model2.predict(x_test2)\n",
|
|
||||||
"acc2 = accuracy_score(y_test, svm_pred2) * 100\n",
|
|
||||||
"accuracies2.append(acc2)\n",
|
|
||||||
"# format with color coded if acc2 > 90\n",
|
|
||||||
"acc2 = f\"\\033[92m{acc2:.2f}\\033[00m\" if acc2 > 90 else f\"{acc2:.2f}\"\n",
|
|
||||||
"print(\"Support Vector Machine Accuracy for sensor 2:\", acc2)\n",
|
|
||||||
"\n",
|
|
||||||
"# 7. XGBoost\n",
|
|
||||||
"xgboost_model = XGBClassifier()\n",
|
|
||||||
"xgboost_model.fit(x_train1, y_train)\n",
|
|
||||||
"xgboost_pred1 = xgboost_model.predict(x_test1)\n",
|
|
||||||
"acc1 = accuracy_score(y_test, xgboost_pred1) * 100\n",
|
|
||||||
"accuracies1.append(acc1)\n",
|
|
||||||
"# format with color coded if acc1 > 90\n",
|
|
||||||
"acc1 = f\"\\033[92m{acc1:.2f}\\033[00m\" if acc1 > 90 else f\"{acc1:.2f}\"\n",
|
|
||||||
"print(\"XGBoost Accuracy:\", acc1)\n",
|
|
||||||
"xgboost_model2 = XGBClassifier()\n",
|
|
||||||
"xgboost_model2.fit(x_train2, y_train)\n",
|
|
||||||
"xgboost_pred2 = xgboost_model2.predict(x_test2)\n",
|
|
||||||
"acc2 = accuracy_score(y_test, xgboost_pred2) * 100\n",
|
|
||||||
"accuracies2.append(acc2)\n",
|
|
||||||
"# format with color coded if acc2 > 90\n",
|
|
||||||
"acc2 = f\"\\033[92m{acc2:.2f}\\033[00m\" if acc2 > 90 else f\"{acc2:.2f}\"\n",
|
|
||||||
"print(\"XGBoost Accuracy:\", acc2)"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -758,8 +714,35 @@
|
|||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
"source": [
|
"source": [
|
||||||
"print(accuracies1)\n",
|
"models_sensor2 = {\n",
|
||||||
"print(accuracies2)"
|
" # \"Random Forest\": RandomForestClassifier(),\n",
|
||||||
|
" # \"Bagged Trees\": BaggingClassifier(estimator=DecisionTreeClassifier(), n_estimators=10),\n",
|
||||||
|
" # \"Decision Tree\": DecisionTreeClassifier(),\n",
|
||||||
|
" # \"KNN\": KNeighborsClassifier(),\n",
|
||||||
|
" # \"LDA\": LinearDiscriminantAnalysis(),\n",
|
||||||
|
" \"SVM\": SVC(),\n",
|
||||||
|
" # \"XGBoost\": XGBClassifier()\n",
|
||||||
|
"}\n",
|
||||||
|
"\n",
|
||||||
|
"results_sensor2 = []\n",
|
||||||
|
"for name, model in models_sensor2.items():\n",
|
||||||
|
" res = train_and_evaluate_model(model, name, \"sensor2\", x_train2, y_train, x_test2, y_test, export='D:/thesis/models/sensor2')\n",
|
||||||
|
" results_sensor2.append(res)\n",
|
||||||
|
" print(f\"{name} on sensor2: Accuracy = {res['accuracy']:.2f}%\")\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"all_results = {\n",
|
||||||
|
" \"sensor1\": results_sensor1,\n",
|
||||||
|
" \"sensor2\": results_sensor2\n",
|
||||||
|
"}\n",
|
||||||
|
"\n",
|
||||||
|
"print(all_results)"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -771,36 +754,48 @@
|
|||||||
"import numpy as np\n",
|
"import numpy as np\n",
|
||||||
"import matplotlib.pyplot as plt\n",
|
"import matplotlib.pyplot as plt\n",
|
||||||
"\n",
|
"\n",
|
||||||
"models = [rf_model, bagged_model, dt_model, knn_model, lda_model, svm_model, xgboost_model]\n",
|
"def prepare_plot_data(results_dict):\n",
|
||||||
"model_names = [\"Random Forest\", \"Bagged Trees\", \"Decision Tree\", \"KNN\", \"LDA\", \"SVM\", \"XGBoost\"]\n",
|
" # Gather unique model names\n",
|
||||||
|
" models_set = {entry['model'] for sensor in results_dict.values() for entry in sensor}\n",
|
||||||
|
" models = sorted(list(models_set))\n",
|
||||||
|
" \n",
|
||||||
|
" # Create dictionaries mapping sensor -> accuracy list ordered by model name\n",
|
||||||
|
" sensor_accuracies = {}\n",
|
||||||
|
" for sensor, entries in results_dict.items():\n",
|
||||||
|
" # Build a mapping: model -> accuracy for the given sensor\n",
|
||||||
|
" mapping = {entry['model']: entry['accuracy'] for entry in entries}\n",
|
||||||
|
" # Order the accuracies consistent with the sorted model names\n",
|
||||||
|
" sensor_accuracies[sensor] = [mapping.get(model, 0) for model in models]\n",
|
||||||
|
" \n",
|
||||||
|
" return models, sensor_accuracies\n",
|
||||||
"\n",
|
"\n",
|
||||||
"bar_width = 0.35 # Width of each bar\n",
|
"def plot_accuracies(models, sensor_accuracies):\n",
|
||||||
"index = np.arange(len(model_names)) # Index for the bars\n",
|
" bar_width = 0.35\n",
|
||||||
|
" x = np.arange(len(models))\n",
|
||||||
|
" sensors = list(sensor_accuracies.keys())\n",
|
||||||
|
" \n",
|
||||||
|
" plt.figure(figsize=(10, 6))\n",
|
||||||
|
" # Assume two sensors for plotting grouped bars\n",
|
||||||
|
" plt.bar(x - bar_width/2, sensor_accuracies[sensors[0]], width=bar_width, color='blue', label=sensors[0])\n",
|
||||||
|
" plt.bar(x + bar_width/2, sensor_accuracies[sensors[1]], width=bar_width, color='orange', label=sensors[1])\n",
|
||||||
|
" \n",
|
||||||
|
" # Add text labels on top of bars\n",
|
||||||
|
" for i, (a1, a2) in enumerate(zip(sensor_accuracies[sensors[0]], sensor_accuracies[sensors[1]])):\n",
|
||||||
|
" plt.text(x[i] - bar_width/2, a1 + 0.1, f\"{a1:.2f}%\", ha='center', va='bottom', color='black')\n",
|
||||||
|
" plt.text(x[i] + bar_width/2, a2 + 0.1, f\"{a2:.2f}%\", ha='center', va='bottom', color='black')\n",
|
||||||
|
" \n",
|
||||||
|
" plt.xlabel('Model Name')\n",
|
||||||
|
" plt.ylabel('Accuracy (%)')\n",
|
||||||
|
" plt.title('Accuracy of Classifiers for Each Sensor')\n",
|
||||||
|
" plt.xticks(x, models)\n",
|
||||||
|
" plt.legend()\n",
|
||||||
|
" plt.ylim(0, 105)\n",
|
||||||
|
" plt.tight_layout()\n",
|
||||||
|
" plt.show()\n",
|
||||||
"\n",
|
"\n",
|
||||||
"# Plotting the bar graph\n",
|
"# Use the functions\n",
|
||||||
"plt.figure(figsize=(14, 8))\n",
|
"models, sensor_accuracies = prepare_plot_data(all_results)\n",
|
||||||
"\n",
|
"plot_accuracies(models, sensor_accuracies)\n"
|
||||||
"# Bar plot for Sensor 1\n",
|
|
||||||
"plt.bar(index, accuracies1, width=bar_width, color='blue', label='Sensor 1')\n",
|
|
||||||
"\n",
|
|
||||||
"# Bar plot for Sensor 2\n",
|
|
||||||
"plt.bar(index + bar_width, accuracies2, width=bar_width, color='orange', label='Sensor 2')\n",
|
|
||||||
"\n",
|
|
||||||
"# Add values on top of each bar\n",
|
|
||||||
"for i, acc1, acc2 in zip(index, accuracies1, accuracies2):\n",
|
|
||||||
" plt.text(i, acc1 + .1, f'{acc1:.2f}%', ha='center', va='bottom', color='black')\n",
|
|
||||||
" plt.text(i + bar_width, acc2 + 1, f'{acc2:.2f}%', ha='center', va='bottom', color='black')\n",
|
|
||||||
"\n",
|
|
||||||
"# Customize the plot\n",
|
|
||||||
"plt.xlabel('Model Name →')\n",
|
|
||||||
"plt.ylabel('Accuracy →')\n",
|
|
||||||
"plt.title('Accuracy of classifiers for Sensors 1 and 2 with 513 features')\n",
|
|
||||||
"plt.xticks(index + bar_width / 2, model_names) # Set x-tick positions\n",
|
|
||||||
"plt.legend()\n",
|
|
||||||
"plt.ylim(0, 100)\n",
|
|
||||||
"\n",
|
|
||||||
"# Show the plot\n",
|
|
||||||
"plt.show()\n"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -844,6 +839,8 @@
|
|||||||
"source": [
|
"source": [
|
||||||
"from sklearn.metrics import accuracy_score, classification_report\n",
|
"from sklearn.metrics import accuracy_score, classification_report\n",
|
||||||
"# 4. Validate on Dataset B\n",
|
"# 4. Validate on Dataset B\n",
|
||||||
|
"from joblib import load\n",
|
||||||
|
"svm_model = load('D:/thesis/models/sensor1/SVM.joblib')\n",
|
||||||
"y_pred_svm = svm_model.predict(X1b)\n",
|
"y_pred_svm = svm_model.predict(X1b)\n",
|
||||||
"\n",
|
"\n",
|
||||||
"# 5. Evaluate\n",
|
"# 5. Evaluate\n",
|
||||||
@@ -851,6 +848,30 @@
|
|||||||
"print(classification_report(y, y_pred_svm))"
|
"print(classification_report(y, y_pred_svm))"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"### Model sensor 1 to predict sensor 2 data"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"from sklearn.metrics import accuracy_score, classification_report\n",
|
||||||
|
"# 4. Validate on Dataset B\n",
|
||||||
|
"from joblib import load\n",
|
||||||
|
"svm_model = load('D:/thesis/models/sensor1/SVM.joblib')\n",
|
||||||
|
"y_pred_svm = svm_model.predict(X2b)\n",
|
||||||
|
"\n",
|
||||||
|
"# 5. Evaluate\n",
|
||||||
|
"print(\"Accuracy on Dataset B:\", accuracy_score(y, y_pred_svm))\n",
|
||||||
|
"print(classification_report(y, y_pred_svm))"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": null,
|
"execution_count": null,
|
||||||
@@ -910,7 +931,7 @@
|
|||||||
"# Plot\n",
|
"# Plot\n",
|
||||||
"disp = ConfusionMatrixDisplay(confusion_matrix=cm, display_labels=labels)\n",
|
"disp = ConfusionMatrixDisplay(confusion_matrix=cm, display_labels=labels)\n",
|
||||||
"disp.plot(cmap=plt.cm.Blues) # You can change colormap\n",
|
"disp.plot(cmap=plt.cm.Blues) # You can change colormap\n",
|
||||||
"plt.title(\"SVM Sensor1 CM Train w/ Dataset A Val w/ Dataset B\")\n",
|
"plt.title(\"SVM Sensor1 CM Train w/ Dataset A Val w/ Dataset B from Sensor2 readings\")\n",
|
||||||
"plt.show()"
|
"plt.show()"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -928,14 +949,14 @@
|
|||||||
"outputs": [],
|
"outputs": [],
|
||||||
"source": [
|
"source": [
|
||||||
"# 1. Predict sensor 1 on Dataset A\n",
|
"# 1. Predict sensor 1 on Dataset A\n",
|
||||||
"y_train_pred = svm_model.predict(x_train1)\n",
|
"y_test_pred = svm_model.predict(x_test1)\n",
|
||||||
"\n",
|
"\n",
|
||||||
"# 2. Import confusion matrix tools\n",
|
"# 2. Import confusion matrix tools\n",
|
||||||
"from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay\n",
|
"from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay\n",
|
||||||
"import matplotlib.pyplot as plt\n",
|
"import matplotlib.pyplot as plt\n",
|
||||||
"\n",
|
"\n",
|
||||||
"# 3. Create and plot confusion matrix\n",
|
"# 3. Create and plot confusion matrix\n",
|
||||||
"cm_train = confusion_matrix(y_train, y_train_pred)\n",
|
"cm_train = confusion_matrix(y_test, y_test_pred)\n",
|
||||||
"labels = svm_model.classes_\n",
|
"labels = svm_model.classes_\n",
|
||||||
"\n",
|
"\n",
|
||||||
"disp = ConfusionMatrixDisplay(confusion_matrix=cm_train, display_labels=labels)\n",
|
"disp = ConfusionMatrixDisplay(confusion_matrix=cm_train, display_labels=labels)\n",
|
||||||
|
|||||||
@@ -55,3 +55,101 @@ def create_ready_data(
|
|||||||
y = np.array([])
|
y = np.array([])
|
||||||
|
|
||||||
return X, y
|
return X, y
|
||||||
|
|
||||||
|
|
||||||
|
def train_and_evaluate_model(
|
||||||
|
model, model_name, sensor_label, x_train, y_train, x_test, y_test, export=None
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Train a machine learning model, evaluate its performance, and optionally export it.
|
||||||
|
|
||||||
|
This function trains the provided model on the training data, evaluates its
|
||||||
|
performance on test data using accuracy score, and can save the trained model
|
||||||
|
to disk if an export path is provided.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
model : estimator object
|
||||||
|
The machine learning model to train.
|
||||||
|
model_name : str
|
||||||
|
Name of the model, used for the export filename and in the returned results.
|
||||||
|
sensor_label : str
|
||||||
|
Label identifying which sensor's data the model is being trained on.
|
||||||
|
x_train : array-like or pandas.DataFrame
|
||||||
|
The training input samples.
|
||||||
|
y_train : array-like
|
||||||
|
The target values for training.
|
||||||
|
x_test : array-like or pandas.DataFrame
|
||||||
|
The test input samples.
|
||||||
|
y_test : array-like
|
||||||
|
The target values for testing.
|
||||||
|
export : str, optional
|
||||||
|
Directory path where the trained model should be saved. If None, model won't be saved.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
dict
|
||||||
|
Dictionary containing:
|
||||||
|
- 'model': model_name (str)
|
||||||
|
- 'sensor': sensor_label (str)
|
||||||
|
- 'accuracy': accuracy percentage (float)
|
||||||
|
|
||||||
|
Example
|
||||||
|
-------
|
||||||
|
>>> from sklearn.svm import SVC
|
||||||
|
>>> from sklearn.model_selection import train_test_split
|
||||||
|
>>> X_train, X_test, y_train, y_test = train_test_split(features, labels, test_size=0.2)
|
||||||
|
>>> result = train_and_evaluate_model(
|
||||||
|
... SVC(),
|
||||||
|
... "SVM",
|
||||||
|
... "sensor1",
|
||||||
|
... X_train,
|
||||||
|
... y_train,
|
||||||
|
... X_test,
|
||||||
|
... y_test,
|
||||||
|
... export="models/sensor1"
|
||||||
|
... )
|
||||||
|
>>> print(f"Model accuracy: {result['accuracy']:.2f}%")
|
||||||
|
"""
|
||||||
|
from sklearn.metrics import accuracy_score
|
||||||
|
|
||||||
|
result = {"model": model_name, "sensor": sensor_label, "success": False}
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Train the model
|
||||||
|
model.fit(x_train, y_train)
|
||||||
|
|
||||||
|
try:
|
||||||
|
y_pred = model.predict(x_test)
|
||||||
|
except Exception as e:
|
||||||
|
result["error"] = f"Prediction error: {str(e)}"
|
||||||
|
return result
|
||||||
|
|
||||||
|
# Calculate accuracy
|
||||||
|
try:
|
||||||
|
accuracy = accuracy_score(y_test, y_pred) * 100
|
||||||
|
result["accuracy"] = accuracy
|
||||||
|
except Exception as e:
|
||||||
|
result["error"] = f"Accuracy calculation error: {str(e)}"
|
||||||
|
return result
|
||||||
|
|
||||||
|
# Export model if requested
|
||||||
|
if export:
|
||||||
|
try:
|
||||||
|
import joblib
|
||||||
|
|
||||||
|
full_path = os.path.join(export, f"{model_name}.joblib")
|
||||||
|
os.makedirs(os.path.dirname(full_path), exist_ok=True)
|
||||||
|
joblib.dump(model, full_path)
|
||||||
|
print(f"Model saved to {full_path}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Warning: Failed to export model to {export}: {str(e)}")
|
||||||
|
result["export_error"] = str(e)
|
||||||
|
# Continue despite export error
|
||||||
|
|
||||||
|
result["success"] = True
|
||||||
|
return result
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
result["error"] = f"Training error: {str(e)}"
|
||||||
|
return result
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ Alur keseluruhan penelitian ini dilakukan melalui tahapan-tahapan sebagai beriku
|
|||||||
|
|
||||||
\begin{figure}[H]
|
\begin{figure}[H]
|
||||||
\centering
|
\centering
|
||||||
\includegraphics[width=0.3\linewidth]{chapters/id/flow.png}
|
\includegraphics[width=0.3\linewidth]{chapters/img/flow.png}
|
||||||
\caption{Diagram alir tahapan penelitian}
|
\caption{Diagram alir tahapan penelitian}
|
||||||
\label{fig:flowchart}
|
\label{fig:flowchart}
|
||||||
\end{figure}
|
\end{figure}
|
||||||
|
|||||||
0
latex/frontmatter/acknowledgement.tex
Normal file
0
latex/frontmatter/acknowledgement.tex
Normal file
78
latex/frontmatter/glossaries.tex
Normal file
78
latex/frontmatter/glossaries.tex
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
% % A new command that enables us to enter bi-lingual (Slovene and English) terms
|
||||||
|
% % syntax: \addterm[options]{label}{Slovene}{Slovene first use}{English}{Slovene
|
||||||
|
% % description}
|
||||||
|
% \newcommand{\addterm}[6][]{
|
||||||
|
% \newglossaryentry{#2}{
|
||||||
|
% name={#3 (angl.\ #5)},
|
||||||
|
% first={#4 (\emph{#5})},
|
||||||
|
% text={#3},
|
||||||
|
% sort={#3},
|
||||||
|
% description={#6},
|
||||||
|
% #1 % pass additional options to \newglossaryentry
|
||||||
|
% }
|
||||||
|
% }
|
||||||
|
|
||||||
|
% % A new command that enables us to enter (English) acronyms with bi-lingual
|
||||||
|
% % (Slovene and English) long versions
|
||||||
|
% % syntax: \addacronym[options]{label}{abbreviation}{Slovene long}{Slovene first
|
||||||
|
% % use long}{English long}{Slovene description}
|
||||||
|
% \newcommand{\addacronym}[7][]{
|
||||||
|
% % Create the main glossary entry with \newacronym
|
||||||
|
% % \newacronym[key-val list]{label}{abbrv}{long}
|
||||||
|
% \newacronym[
|
||||||
|
% name={#4 (angl.\ #6,\ #3)},
|
||||||
|
% first={\emph{#5} (angl.\ \emph{#6},\ \emph{#3})},
|
||||||
|
% sort={#4},
|
||||||
|
% description={#7},
|
||||||
|
% #1 % pass additional options to \newglossaryentry
|
||||||
|
% ]
|
||||||
|
% {#2}{#3}{#4}
|
||||||
|
% % Create a cross-reference from the abbreviation to the main glossary entry by
|
||||||
|
% % creating an auxiliary glossary entry (note: we set the label of this entry
|
||||||
|
% % to '<original label>_auxiliary' to avoid clashes)
|
||||||
|
% \newglossaryentry{#2_auxiliary}{
|
||||||
|
% name={#3},
|
||||||
|
% sort={#3},
|
||||||
|
% description={\makefirstuc{#6}},
|
||||||
|
% see=[See:]{#2}
|
||||||
|
% }
|
||||||
|
% }
|
||||||
|
|
||||||
|
% % Change the text of the cross-reference links to the Slovene long version.
|
||||||
|
% \renewcommand*{\glsseeitemformat}[1]{\emph{\acrlong{#1}}.}
|
||||||
|
|
||||||
|
% Define the Indonesian term and link it to the English term
|
||||||
|
\newglossaryentry{jaringansaraf}{
|
||||||
|
name=Jaringan Saraf,
|
||||||
|
description={The Indonesian term for \gls{nn}}
|
||||||
|
}
|
||||||
|
% \newglossaryentry{pemelajaranmesin}{
|
||||||
|
% name=Pemelajaran Mesin,
|
||||||
|
% description={Lihat \gls{machinelearning}}
|
||||||
|
% }
|
||||||
|
|
||||||
|
% Define the English term and link it to its acronym
|
||||||
|
\newglossaryentry{neuralnetwork}{
|
||||||
|
name=Neural Network,
|
||||||
|
description={A computational model inspired by the human brain, see \gls{nn}}
|
||||||
|
}
|
||||||
|
|
||||||
|
% \newglossaryentry{machinelearning}{
|
||||||
|
% name=Machine Learning,
|
||||||
|
% description={A program or system that trains a model from input data. The trained model can make useful predictions from new (never-before-seen) data drawn from the same distribution as the one used to train the model.}}
|
||||||
|
% \newglossaryentry{pemelajaranmesin}{
|
||||||
|
% name={pemelajaran mesin (angl.\ #5)},
|
||||||
|
% first={pemelajaran mesin (\emph{machine learning})},
|
||||||
|
% text={pemelajaran mesin},
|
||||||
|
% sort={ },
|
||||||
|
% description={#6},
|
||||||
|
% #1 % pass additional options to \newglossaryentry
|
||||||
|
% }
|
||||||
|
\longnewglossaryentry{machinelearning}{name={machine learning}}
|
||||||
|
{A program or system that trains a model from input data. The trained model can make useful predictions from new (never-before-seen) data drawn from the same distribution as the one used to train the model.}
|
||||||
|
\newterm[see={machinelearning}]{pemelajaranmesin}
|
||||||
|
% \newglossaryentry{pemelajaran mesin}{}
|
||||||
|
% \addterm{machinelearning}{pemelajaran mesin}{pemelajaran mesin}{machine learning}{A program or system that trains a model from input data. The trained model can make useful predictions from new (never-before-seen) data drawn from the same distribution as the one used to train the model.}
|
||||||
|
\newacronym
|
||||||
|
[description={statistical pattern recognition technique}]
|
||||||
|
{svm}{SVM}{support vector machine}
|
||||||
@@ -1,14 +1,18 @@
|
|||||||
\documentclass[draftmark]{thesis}
|
\documentclass[draftmark]{thesis}
|
||||||
|
|
||||||
% Title Information
|
% Metadata
|
||||||
\setthesisinfo
|
\title{Prediksi Lokasi Kerusakan dengan Machine Learning}
|
||||||
{Prediksi Lokasi Kerusakan dengan Machine Learning}
|
\author{Rifqi Damar Panuluh}
|
||||||
{Rifqi Damar Panuluh}
|
\date{\today}
|
||||||
{20210110224}
|
\authorid{20210110224}
|
||||||
{PROGRAM STUDI TEKNIK SIPIL}
|
\firstadvisor{Ir. Muhammad Ibnu Syamsi, Ph.D.}
|
||||||
{FAKULTAS TEKNIK}
|
\secondadvisor{}
|
||||||
{UNIVERSITAS MUHAMMADIYAH YOGYAKARTA}
|
\headdepartement{Puji Harsanto, S.T., M.T., Ph.D.}
|
||||||
{2025}
|
\headdepartementid{19740607201404123064}
|
||||||
|
\faculty{Fakultas Teknik}
|
||||||
|
\program{Program Studi Teknik Sipil}
|
||||||
|
\university{Universitas Muhammadiyah Yogyakarta}
|
||||||
|
\yearofsubmission{2025}
|
||||||
|
|
||||||
% Input preamble
|
% Input preamble
|
||||||
\input{preamble/packages}
|
\input{preamble/packages}
|
||||||
@@ -16,22 +20,19 @@
|
|||||||
\input{preamble/macros}
|
\input{preamble/macros}
|
||||||
|
|
||||||
\begin{document}
|
\begin{document}
|
||||||
|
% \input{frontmatter/maketitle}
|
||||||
\maketitle
|
% \input{frontmatter/maketitle_secondary}
|
||||||
\frontmatter
|
\frontmatter
|
||||||
\input{frontmatter/approval}\clearpage
|
% \input{frontmatter/approval}\clearpage
|
||||||
\input{frontmatter/originality}\clearpage
|
% \input{frontmatter/originality}\clearpage
|
||||||
\input{frontmatter/acknowledgement}\clearpage
|
% \input{frontmatter/acknowledgement}\clearpage
|
||||||
\tableofcontents
|
% \tableofcontents
|
||||||
\clearpage
|
\clearpage
|
||||||
\mainmatter
|
\mainmatter
|
||||||
\pagestyle{fancyplain}
|
\pagestyle{fancyplain}
|
||||||
% Include content
|
|
||||||
\include{content/abstract}
|
|
||||||
\include{content/introduction}
|
|
||||||
\include{chapters/01_introduction}
|
\include{chapters/01_introduction}
|
||||||
\include{content/chapter2}
|
\include{chapters/id/02_literature_review/index}
|
||||||
\include{content/conclusion}
|
\include{chapters/id/03_methodology/index}
|
||||||
|
|
||||||
% Bibliography
|
% Bibliography
|
||||||
% \bibliographystyle{IEEEtran}
|
% \bibliographystyle{IEEEtran}
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
\newcommand{\studentname}{Rifqi Damar Panuluh}
|
|
||||||
\newcommand{\studentid}{20210110224}
|
|
||||||
\newcommand{\thesistitle}{Prediksi Lokasi Kerusakan dengan Machine Learning}
|
|
||||||
\newcommand{\firstadvisor}{Ir. Muhammad Ibnu Syamsi, Ph.D.}
|
|
||||||
\newcommand{\secondadvisor}{}
|
|
||||||
\newcommand{\headdepartement}{Puji Harsanto, S.T. M.T., Ph.D.}
|
|
||||||
\newcommand{\headdepartementid}{19740607201404123064}
|
|
||||||
\newcommand{\faculty}{Fakultas Teknik}
|
|
||||||
\newcommand{\program}{Teknik Sipil}
|
|
||||||
\newcommand{\university}{Universitas Muhammadiyah Yogyakarta}
|
|
||||||
\newcommand{\yearofsubmission}{2025}
|
|
||||||
230
latex/thesis.cls
230
latex/thesis.cls
@@ -1,7 +1,7 @@
|
|||||||
\NeedsTeXFormat{LaTeX2e}
|
\NeedsTeXFormat{LaTeX2e}
|
||||||
\ProvidesClass{thesis}[2025/05/10 Bachelor Thesis Class]
|
\ProvidesClass{thesis}[2025/05/10 Bachelor Thesis Class]
|
||||||
|
|
||||||
\newif\if@draftmark
|
\newif\if@draftmark \@draftmarkfalse
|
||||||
\@draftmarkfalse
|
\@draftmarkfalse
|
||||||
|
|
||||||
\DeclareOption{draftmark}{\@draftmarktrue}
|
\DeclareOption{draftmark}{\@draftmarktrue}
|
||||||
@@ -12,6 +12,7 @@
|
|||||||
\RequirePackage{polyglossia}
|
\RequirePackage{polyglossia}
|
||||||
\RequirePackage{fontspec}
|
\RequirePackage{fontspec}
|
||||||
\RequirePackage{titlesec}
|
\RequirePackage{titlesec}
|
||||||
|
\RequirePackage{titling}
|
||||||
\RequirePackage{fancyhdr}
|
\RequirePackage{fancyhdr}
|
||||||
\RequirePackage{geometry}
|
\RequirePackage{geometry}
|
||||||
\RequirePackage{setspace}
|
\RequirePackage{setspace}
|
||||||
@@ -24,30 +25,31 @@
|
|||||||
\RequirePackage{svg} % Allows including SVG images directly
|
\RequirePackage{svg} % Allows including SVG images directly
|
||||||
\RequirePackage{indentfirst} % Makes first paragraph after headings indented
|
\RequirePackage{indentfirst} % Makes first paragraph after headings indented
|
||||||
\RequirePackage{float} % Provides [H] option to force figure/table placement
|
\RequirePackage{float} % Provides [H] option to force figure/table placement
|
||||||
|
\RequirePackage[style=apa, backend=biber]{biblatex}
|
||||||
|
\RequirePackage[acronym, nogroupskip, toc]{glossaries}
|
||||||
% Polyglossia set language
|
% Polyglossia set language
|
||||||
+ \setdefaultlanguage[variant=indonesian]{malay} % Proper Indonesian language setup
|
\setdefaultlanguage[variant=indonesian]{malay} % Proper Indonesian language setup
|
||||||
+ \setotherlanguage{english} % Enables English as secondary language
|
\setotherlanguage{english} % Enables English as secondary language
|
||||||
|
\DefineBibliographyStrings{english}{% % Customizes bibliography text
|
||||||
+ \DefineBibliographyStrings{english}{% % Customizes bibliography text
|
andothers={dkk\adddot}, % Changes "et al." to "dkk."
|
||||||
+ andothers={dkk\adddot}, % Changes "et al." to "dkk."
|
pages={hlm\adddot}, % Changes "pp." to "hlm."
|
||||||
+ pages={hlm\adddot}, % Changes "pp." to "hlm."
|
}
|
||||||
+ }
|
|
||||||
|
|
||||||
% Conditionally load the watermark package and settings
|
% Conditionally load the watermark package and settings
|
||||||
\if@draftmark
|
\if@draftmark
|
||||||
\RequirePackage{draftwatermark}
|
\RequirePackage{draftwatermark}
|
||||||
\SetWatermarkText{nuluh/thesis (wip) draft: \today}
|
\SetWatermarkText{nuluh/thesis (wip) [draft: \today]}
|
||||||
\SetWatermarkColor[gray]{0.8} % Opacity: 0.8 = 20% transparent
|
\SetWatermarkColor[gray]{0.8} % Opacity: 0.8 = 20% transparent
|
||||||
\SetWatermarkFontSize{1.5cm}
|
\SetWatermarkFontSize{1.5cm}
|
||||||
\SetWatermarkAngle{90}
|
\SetWatermarkAngle{90}
|
||||||
\SetWatermarkHorCenter{1.5cm}
|
\SetWatermarkHorCenter{1.5cm}
|
||||||
|
\RequirePackage[left]{lineno}
|
||||||
|
\linenumbers
|
||||||
\fi
|
\fi
|
||||||
|
|
||||||
% Page layout
|
% Page layout
|
||||||
\geometry{left=3cm, top=3cm, right=3cm, bottom=3cm}
|
\geometry{left=4cm, top=3cm, right=3cm, bottom=3cm}
|
||||||
\setlength{\parskip}{0.5em}
|
\setlength{\parskip}{0.5em}
|
||||||
\setlength{\parindent}{0pt}
|
|
||||||
\onehalfspacing
|
\onehalfspacing
|
||||||
|
|
||||||
% Fonts
|
% Fonts
|
||||||
@@ -56,19 +58,45 @@
|
|||||||
\setsansfont{Arial}
|
\setsansfont{Arial}
|
||||||
\setmonofont{Courier New}
|
\setmonofont{Courier New}
|
||||||
|
|
||||||
% Metadata commands
|
\makeatletter
|
||||||
\input{metadata}
|
% Extracting the Year from \today
|
||||||
|
\newcommand{\theyear}{%
|
||||||
\newcommand{\setthesisinfo}[7]{%
|
\expandafter\@car\expandafter\@gobble\the\year\@nil
|
||||||
\renewcommand{\thesistitle}{#1}%
|
|
||||||
\renewcommand{\studentname}{#2}%
|
|
||||||
\renewcommand{\studentid}{#3}%
|
|
||||||
\renewcommand{\program}{#4}%
|
|
||||||
\renewcommand{\faculty}{#5}%
|
|
||||||
\renewcommand{\university}{#6}%
|
|
||||||
\renewcommand{\yearofsubmission}{#7}%
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
% Declare internal macros as initially empty
|
||||||
|
\newcommand{\@authorid}{}
|
||||||
|
\newcommand{\@firstadvisor}{}
|
||||||
|
\newcommand{\@secondadvisor}{}
|
||||||
|
\newcommand{\@headdepartement}{}
|
||||||
|
\newcommand{\@headdepartementid}{}
|
||||||
|
\newcommand{\@faculty}{}
|
||||||
|
\newcommand{\@program}{}
|
||||||
|
\newcommand{\@university}{}
|
||||||
|
\newcommand{\@yearofsubmission}{}
|
||||||
|
|
||||||
|
% Define user commands to set these values.
|
||||||
|
\newcommand{\authorid}[1]{\gdef\@authorid{#1}}
|
||||||
|
\newcommand{\firstadvisor}[1]{\gdef\@firstadvisor{#1}}
|
||||||
|
\newcommand{\secondadvisor}[1]{\gdef\@secondadvisor{#1}}
|
||||||
|
\newcommand{\headdepartement}[1]{\gdef\@headdepartement{#1}}
|
||||||
|
\newcommand{\headdepartementid}[1]{\gdef\@headdepartementid{#1}}
|
||||||
|
\newcommand{\faculty}[1]{\gdef\@faculty{#1}}
|
||||||
|
\newcommand{\program}[1]{\gdef\@program{#1}}
|
||||||
|
\newcommand{\university}[1]{\gdef\@university{#1}}
|
||||||
|
\newcommand{\yearofsubmission}[1]{\gdef\@yearofsubmission{#1}}
|
||||||
|
|
||||||
|
% Now expose robust “the‑” getters to access the values
|
||||||
|
\newcommand{\theauthorid}{\@authorid}
|
||||||
|
\newcommand{\thefirstadvisor}{\@firstadvisor}
|
||||||
|
\newcommand{\thesecondadvisor}{\@secondadvisor}
|
||||||
|
\newcommand{\theheaddepartement}{\@headdepartement}
|
||||||
|
\newcommand{\theheaddepartementid}{\@headdepartementid}
|
||||||
|
\newcommand{\thefaculty}{\@faculty}
|
||||||
|
\newcommand{\theprogram}{\@program}
|
||||||
|
\newcommand{\theuniversity}{\@university}
|
||||||
|
\newcommand{\theyearofsubmission}{\@yearofsubmission}
|
||||||
|
\makeatother
|
||||||
% % Header and footer
|
% % Header and footer
|
||||||
\fancypagestyle{fancy}{%
|
\fancypagestyle{fancy}{%
|
||||||
\fancyhf{}
|
\fancyhf{}
|
||||||
@@ -110,11 +138,6 @@
|
|||||||
\renewcommand{\cftchappresnum}{BAB~}
|
\renewcommand{\cftchappresnum}{BAB~}
|
||||||
\renewcommand{\cftchapaftersnum}{\quad}
|
\renewcommand{\cftchapaftersnum}{\quad}
|
||||||
|
|
||||||
% \titlespacing*{\chapter}{0pt}{-10pt}{20pt}
|
|
||||||
|
|
||||||
% Redefine \maketitle
|
|
||||||
\renewcommand{\maketitle}{\input{frontmatter/maketitle}}
|
|
||||||
|
|
||||||
% Chapter & Section format
|
% Chapter & Section format
|
||||||
\renewcommand{\cftchapfont}{\normalsize\MakeUppercase}
|
\renewcommand{\cftchapfont}{\normalsize\MakeUppercase}
|
||||||
% \renewcommand{\cftsecfont}{}
|
% \renewcommand{\cftsecfont}{}
|
||||||
@@ -136,11 +159,15 @@
|
|||||||
\setlength{\cftsubsecnumwidth}{2.5em}
|
\setlength{\cftsubsecnumwidth}{2.5em}
|
||||||
\setlength{\cftfignumwidth}{5em}
|
\setlength{\cftfignumwidth}{5em}
|
||||||
\setlength{\cfttabnumwidth}{4em}
|
\setlength{\cfttabnumwidth}{4em}
|
||||||
\renewcommand \cftchapdotsep{1} % Denser dots (closer together) https://tex.stackexchange.com/a/273764
|
\renewcommand \cftchapdotsep{1} % https://tex.stackexchange.com/a/273764
|
||||||
\renewcommand \cftsecdotsep{1} % Apply to sections too
|
\renewcommand \cftsecdotsep{1} % https://tex.stackexchange.com/a/273764
|
||||||
\renewcommand \cftsubsecdotsep{1} % Apply to subsections too
|
\renewcommand \cftsubsecdotsep{1} % https://tex.stackexchange.com/a/273764
|
||||||
|
\renewcommand \cftfigdotsep{1.5} % https://tex.stackexchange.com/a/273764
|
||||||
|
\renewcommand \cfttabdotsep{1.5} % https://tex.stackexchange.com/a/273764
|
||||||
\renewcommand{\cftchapleader}{\normalfont\cftdotfill{\cftsecdotsep}}
|
\renewcommand{\cftchapleader}{\normalfont\cftdotfill{\cftsecdotsep}}
|
||||||
\renewcommand{\cftchappagefont}{\normalfont}
|
\renewcommand{\cftchappagefont}{\normalfont}
|
||||||
|
|
||||||
|
% Add Prefix in the Lof and LoT entries
|
||||||
\renewcommand{\cftfigpresnum}{\figurename~}
|
\renewcommand{\cftfigpresnum}{\figurename~}
|
||||||
\renewcommand{\cfttabpresnum}{\tablename~}
|
\renewcommand{\cfttabpresnum}{\tablename~}
|
||||||
|
|
||||||
@@ -165,6 +192,147 @@
|
|||||||
% \renewcommand{\cfttoctitlefont}{\bfseries\MakeUppercase}
|
% \renewcommand{\cfttoctitlefont}{\bfseries\MakeUppercase}
|
||||||
% \renewcommand{\cftaftertoctitle}{\vskip 2em}
|
% \renewcommand{\cftaftertoctitle}{\vskip 2em}
|
||||||
|
|
||||||
|
% Defines a new glossary called “notation”
|
||||||
|
\newglossary[nlg]{notation}{not}{ntn}{Notation}
|
||||||
|
|
||||||
|
% Define the header for the location column
|
||||||
|
\providecommand*{\locationname}{Location}
|
||||||
|
|
||||||
|
% Define the new glossary style called 'mylistalt' for main glossaries
|
||||||
|
\makeatletter
|
||||||
|
\newglossarystyle{mylistalt}{%
|
||||||
|
% start the list, initializing glossaries internals
|
||||||
|
\renewenvironment{theglossary}%
|
||||||
|
{\glslistinit\begin{enumerate}}%
|
||||||
|
{\end{enumerate}}%
|
||||||
|
% suppress all headers/groupskips
|
||||||
|
\renewcommand*{\glossaryheader}{}%
|
||||||
|
\renewcommand*{\glsgroupheading}[1]{}%
|
||||||
|
\renewcommand*{\glsgroupskip}{}%
|
||||||
|
% main entries: let \item produce "1." etc., then break
|
||||||
|
\renewcommand*{\glossentry}[2]{%
|
||||||
|
\item \glstarget{##1}{\glossentryname{##1}}%
|
||||||
|
\mbox{}\\
|
||||||
|
\glossentrydesc{##1}\space
|
||||||
|
[##2] % appears on page x
|
||||||
|
}%
|
||||||
|
% sub-entries as separate paragraphs, still aligned
|
||||||
|
\renewcommand*{\subglossentry}[3]{%
|
||||||
|
\par
|
||||||
|
\glssubentryitem{##2}%
|
||||||
|
\glstarget{##2}{\strut}\space
|
||||||
|
\glossentrydesc{##2}\space ##3%
|
||||||
|
}%
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
% Define the new glossary style 'altlong3customheader' for notation
|
||||||
|
\newglossarystyle{altlong3customheader}{%
|
||||||
|
% The glossary will be a longtable environment with three columns:
|
||||||
|
% 1. Symbol (left-aligned)
|
||||||
|
% 2. Description (paragraph, width \glsdescwidth)
|
||||||
|
% 3. Location (paragraph, width \glspagelistwidth)
|
||||||
|
\renewenvironment{theglossary}%
|
||||||
|
{\begin{longtable}{lp{\glsdescwidth}p{\glspagelistwidth}}}%
|
||||||
|
{\end{longtable}}%
|
||||||
|
% Define the table header row
|
||||||
|
\renewcommand*{\symbolname}{Simbol}
|
||||||
|
\renewcommand*{\descriptionname}{Keterangan}
|
||||||
|
\renewcommand*{\locationname}{Halaman}
|
||||||
|
\renewcommand*{\glossaryheader}{%
|
||||||
|
\bfseries\symbolname & \bfseries\descriptionname & \bfseries\locationname \tabularnewline\endhead}%
|
||||||
|
% Suppress group headings (e.g., A, B, C...)
|
||||||
|
\renewcommand*{\glsgroupheading}[1]{}%
|
||||||
|
% Define how a main glossary entry is displayed
|
||||||
|
% ##1 is the entry label
|
||||||
|
% ##2 is the location list (page numbers)
|
||||||
|
\renewcommand{\glossentry}[2]{%
|
||||||
|
\glsentryitem{##1}% Inserts entry number if entrycounter option is used
|
||||||
|
\glstarget{##1}{\glossentryname{##1}} & % Column 1: Symbol (with hyperlink target)
|
||||||
|
\glossentrydesc{##1}\glspostdescription & % Column 2: Description (with post-description punctuation)
|
||||||
|
##2\tabularnewline % Column 3: Location list
|
||||||
|
}%
|
||||||
|
% Define how a sub-entry is displayed
|
||||||
|
% ##1 is the sub-entry level (e.g., 1 for first sub-level)
|
||||||
|
% ##2 is the entry label
|
||||||
|
% ##3 is the location list
|
||||||
|
\renewcommand{\subglossentry}[3]{%
|
||||||
|
& % Column 1 (Symbol) is left blank for sub-entries to create an indented look
|
||||||
|
\glssubentryitem{##2}% Inserts sub-entry number if subentrycounter is used
|
||||||
|
\glstarget{##2}{\strut}\glossentrydesc{##2}\glspostdescription & % Column 2: Description (target on strut for hyperlink)
|
||||||
|
##3\tabularnewline % Column 3: Location list
|
||||||
|
}%
|
||||||
|
% Define the skip between letter groups (if group headings were enabled)
|
||||||
|
% For 3 columns, we need 2 ampersands for a full blank row if not using \multicolumn
|
||||||
|
\ifglsnogroupskip
|
||||||
|
\renewcommand*{\glsgroupskip}{}%
|
||||||
|
\else
|
||||||
|
\renewcommand*{\glsgroupskip}{& & \tabularnewline}%
|
||||||
|
\fi
|
||||||
|
}
|
||||||
|
|
||||||
|
% Define a new style 'supercol' based on 'super' for acronyms glossaries
|
||||||
|
\newglossarystyle{supercol}{%
|
||||||
|
\setglossarystyle{super}% inherit everything from the original
|
||||||
|
% override just the main-entry format:
|
||||||
|
\renewcommand*{\glossentry}[2]{%
|
||||||
|
\glsentryitem{##1}%
|
||||||
|
\glstarget{##1}{\glossentryname{##1}}\space % <-- added colon here
|
||||||
|
&: \glossentrydesc{##1}\glspostdescription\space ##2\tabularnewline
|
||||||
|
}%
|
||||||
|
% likewise for sub‐entries, if you want a colon there too:
|
||||||
|
\renewcommand*{\subglossentry}[3]{%
|
||||||
|
&:
|
||||||
|
\glssubentryitem{##2}%
|
||||||
|
\glstarget{##2}{\strut}\glossentryname{##2}\space % <-- and here
|
||||||
|
\glossentrydesc{##2}\glspostdescription\space ##3\tabularnewline
|
||||||
|
}%
|
||||||
|
}
|
||||||
|
\makeatother
|
||||||
|
|
||||||
|
% A new command that enables us to enter bi-lingual (Bahasa Indonesia and English) terms
|
||||||
|
% syntax: \addterm[options]{label}{Bahasa Indonesia}{Bahasa Indonesia first use}{English}{Bahasa Indonesia
|
||||||
|
% description}
|
||||||
|
\newcommand{\addterm}[6][]{
|
||||||
|
\newglossaryentry{#2}{
|
||||||
|
name={#3 (angl.\ #5)},
|
||||||
|
first={#4 (\emph{#5})},
|
||||||
|
text={#3},
|
||||||
|
sort={#3},
|
||||||
|
description={#6},
|
||||||
|
#1 % pass additional options to \newglossaryentry
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
% A new command that enables us to enter (English) acronyms with bi-lingual
|
||||||
|
% (Bahasa Indonesia and English) long versions
|
||||||
|
% syntax: \addacronym[options]{label}{abbreviation}{Bahasa Indonesia long}{Bahasa Indonesia first
|
||||||
|
% use long}{English long}{Bahasa Indonesia description}
|
||||||
|
\newcommand{\addacronym}[7][]{
|
||||||
|
% Create the main glossary entry with \newacronym
|
||||||
|
% \newacronym[key-val list]{label}{abbrv}{long}
|
||||||
|
\newacronym[
|
||||||
|
name={#4 (angl.\ #6,\ #3)},
|
||||||
|
first={\emph{#5} (angl.\ \emph{#6},\ \emph{#3})},
|
||||||
|
sort={#4},
|
||||||
|
description={#7},
|
||||||
|
#1 % pass additional options to \newglossaryentry
|
||||||
|
]
|
||||||
|
{#2}{#3}{#4}
|
||||||
|
% Create a cross-reference from the abbreviation to the main glossary entry by
|
||||||
|
% creating an auxiliary glossary entry (note: we set the label of this entry
|
||||||
|
% to '<original label>_auxiliary' to avoid clashes)
|
||||||
|
\newglossaryentry{#2_auxiliary}{
|
||||||
|
name={#3},
|
||||||
|
sort={#3},
|
||||||
|
description={\makefirstuc{#6}},
|
||||||
|
see=[See:]{#2}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
% Change the text of the cross-reference links to the Bahasa Indonesia long version.
|
||||||
|
\renewcommand*{\glsseeitemformat}[1]{\emph{\acrlong{#1}}.}
|
||||||
|
|
||||||
% % Apply a custom fancyhdr layout only on the first page of each \chapter, and use no header/footer elsewhere
|
% % Apply a custom fancyhdr layout only on the first page of each \chapter, and use no header/footer elsewhere
|
||||||
% % \let\oldchapter\chapter
|
% % \let\oldchapter\chapter
|
||||||
% % \renewcommand{\chapter}{%
|
% % \renewcommand{\chapter}{%
|
||||||
|
|||||||
Reference in New Issue
Block a user