Compare commits
53 Commits
feature/10
...
latex/54-d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4a796694bf | ||
|
|
6357136e6c | ||
|
|
c7584e2dd8 | ||
|
|
80ee9a3ec4 | ||
|
|
f9f346a57e | ||
|
|
cb380219f9 | ||
|
|
804c178175 | ||
|
|
28681017ad | ||
|
|
ff64f3a3ab | ||
|
|
58a316d9c8 | ||
|
|
020028eed8 | ||
|
|
35e25ba4c6 | ||
|
|
8ed1437d6d | ||
|
|
96556a1186 | ||
|
|
0a63aab211 | ||
|
|
c8653f53ea | ||
|
|
48ea879863 | ||
|
|
69afdb1ad1 | ||
|
|
db2d9299e6 | ||
|
|
d5ba1ac0cd | ||
|
|
144f406226 | ||
|
|
e6f8820989 | ||
|
|
59aa124305 | ||
|
|
2de04a6ea6 | ||
|
|
48075a590e | ||
|
|
c28e79b022 | ||
|
|
b890e556cf | ||
|
|
fa6e1ff72b | ||
|
|
a2e339a0a0 | ||
|
|
2decff0cfb | ||
|
|
8b4eedab8a | ||
|
|
a1fbe8bd93 | ||
|
|
832b6c49db | ||
|
|
9618714d3c | ||
|
|
b229967e05 | ||
|
|
f41edaaa91 | ||
|
|
e9c06e1ac1 | ||
|
|
2f54e91197 | ||
|
|
758255a24e | ||
|
|
ff5578652f | ||
|
|
db2c5d3a4e | ||
|
|
ea978de872 | ||
|
|
465d257850 | ||
|
|
d12eea0acf | ||
|
|
0306f28a68 | ||
|
|
9da3dae709 | ||
|
|
41086e95ad | ||
|
|
adde35ed7e | ||
|
|
b2684c23f6 | ||
|
|
8a499a04fb | ||
|
|
118c56c12d | ||
|
|
3860f2cc5b | ||
|
|
553140fe3c |
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
*.ipynb filter=nbstripout
|
||||||
115
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
115
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
name: Bug Report
|
||||||
|
description: Report a bug or unexpected behavior
|
||||||
|
title: "[BUG] "
|
||||||
|
labels: ["bug"]
|
||||||
|
assignees:
|
||||||
|
- ${{github.actor}}
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
Thanks for taking the time to fill out this bug report!
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: description
|
||||||
|
attributes:
|
||||||
|
label: Bug Description
|
||||||
|
description: A clear and concise description of what the bug is
|
||||||
|
placeholder: When I run the script, it crashes when processing large datasets...
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: reproduction
|
||||||
|
attributes:
|
||||||
|
label: Steps to Reproduce
|
||||||
|
description: Steps to reproduce the behavior
|
||||||
|
placeholder: |
|
||||||
|
1. Go to notebook '...'
|
||||||
|
2. Run cell #...
|
||||||
|
3. See error
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: expected
|
||||||
|
attributes:
|
||||||
|
label: Expected Behavior
|
||||||
|
description: What did you expect to happen?
|
||||||
|
placeholder: The analysis should complete successfully and generate the visualization
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: actual
|
||||||
|
attributes:
|
||||||
|
label: Actual Behavior
|
||||||
|
description: What actually happened?
|
||||||
|
placeholder: The script crashes with a memory error after processing 1000 samples
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: logs
|
||||||
|
attributes:
|
||||||
|
label: Error Logs
|
||||||
|
description: Paste any relevant logs or error messages
|
||||||
|
render: shell
|
||||||
|
placeholder: |
|
||||||
|
Traceback (most recent call last):
|
||||||
|
File "script.py", line 42, in <module>
|
||||||
|
main()
|
||||||
|
File "script.py", line 28, in main
|
||||||
|
process_data(data)
|
||||||
|
MemoryError: ...
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
|
||||||
|
- type: dropdown
|
||||||
|
id: component
|
||||||
|
attributes:
|
||||||
|
label: Component
|
||||||
|
description: Which part of the thesis project is affected?
|
||||||
|
options:
|
||||||
|
- LaTeX Document
|
||||||
|
- Python Source Code
|
||||||
|
- Jupyter Notebook
|
||||||
|
- Data Processing
|
||||||
|
- ML Model
|
||||||
|
- Visualization
|
||||||
|
- Build/Environment
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: input
|
||||||
|
id: version
|
||||||
|
attributes:
|
||||||
|
label: Version/Commit
|
||||||
|
description: Which version or commit hash are you using?
|
||||||
|
placeholder: v0.2.3 or 8d5b9a7
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: environment
|
||||||
|
attributes:
|
||||||
|
label: Environment
|
||||||
|
description: Information about your environment
|
||||||
|
placeholder: |
|
||||||
|
- OS: [e.g. Ubuntu 22.04]
|
||||||
|
- Python: [e.g. 3.9.5]
|
||||||
|
- Relevant packages and versions:
|
||||||
|
- numpy: 1.22.3
|
||||||
|
- scikit-learn: 1.0.2
|
||||||
|
- tensorflow: 2.9.1
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: additional
|
||||||
|
attributes:
|
||||||
|
label: Additional Context
|
||||||
|
description: Any other context or screenshots about the problem
|
||||||
|
placeholder: Add any other context about the problem here...
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
12
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
12
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
blank_issues_enabled: false
|
||||||
|
contact_links:
|
||||||
|
- name: Documentation
|
||||||
|
url: ../docs/README.md
|
||||||
|
about: Check the documentation before creating an issue
|
||||||
|
|
||||||
|
# Template configurations
|
||||||
|
templates:
|
||||||
|
- name: bug_report.yml
|
||||||
|
- name: feature_request.yml
|
||||||
|
- name: experiment.yml
|
||||||
|
- name: documentation.yml
|
||||||
116
.github/ISSUE_TEMPLATE/documentation.yml
vendored
Normal file
116
.github/ISSUE_TEMPLATE/documentation.yml
vendored
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
name: Documentation
|
||||||
|
description: Improvements or additions to documentation
|
||||||
|
title: "[DOC] "
|
||||||
|
labels: ["documentation"]
|
||||||
|
assignees:
|
||||||
|
- ${{github.actor}}
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
Use this template for documentation-related tasks for your thesis project.
|
||||||
|
|
||||||
|
- type: dropdown
|
||||||
|
id: doc_type
|
||||||
|
attributes:
|
||||||
|
label: Documentation Type
|
||||||
|
description: What type of documentation is this issue about?
|
||||||
|
options:
|
||||||
|
- Thesis Chapter/Section
|
||||||
|
- Code Documentation
|
||||||
|
- Experiment Documentation
|
||||||
|
- README/Project Documentation
|
||||||
|
- Literature Review
|
||||||
|
- Methodology Description
|
||||||
|
- Results Analysis
|
||||||
|
- API Reference
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: description
|
||||||
|
attributes:
|
||||||
|
label: Description
|
||||||
|
description: Describe what needs to be documented
|
||||||
|
placeholder: Need to document the data preprocessing pipeline including all transformation steps and rationale
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: current_state
|
||||||
|
attributes:
|
||||||
|
label: Current State
|
||||||
|
description: What's the current state of the documentation (if any)?
|
||||||
|
placeholder: Currently there are some comments in the code but no comprehensive documentation of the preprocessing steps
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: proposed_changes
|
||||||
|
attributes:
|
||||||
|
label: Proposed Changes
|
||||||
|
description: What specific documentation changes do you want to make?
|
||||||
|
placeholder: |
|
||||||
|
1. Create a dedicated markdown file describing each preprocessing step
|
||||||
|
2. Add docstrings to all preprocessing functions
|
||||||
|
3. Create a diagram showing the data flow
|
||||||
|
4. Document parameter choices and their justification
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: input
|
||||||
|
id: location
|
||||||
|
attributes:
|
||||||
|
label: Documentation Location
|
||||||
|
description: Where will this documentation be stored?
|
||||||
|
placeholder: docs/data_preprocessing.md or src/preprocessing/README.md
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: dropdown
|
||||||
|
id: priority
|
||||||
|
attributes:
|
||||||
|
label: Priority
|
||||||
|
description: How important is this documentation?
|
||||||
|
options:
|
||||||
|
- Critical (required for thesis)
|
||||||
|
- High (important for understanding)
|
||||||
|
- Medium (helpful but not urgent)
|
||||||
|
- Low (nice to have)
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: dropdown
|
||||||
|
id: audience
|
||||||
|
attributes:
|
||||||
|
label: Target Audience
|
||||||
|
description: Who is the primary audience for this documentation?
|
||||||
|
options:
|
||||||
|
- Thesis Committee/Reviewers
|
||||||
|
- Future Self
|
||||||
|
- Other Researchers
|
||||||
|
- Technical Readers
|
||||||
|
- Non-technical Readers
|
||||||
|
- Multiple Audiences
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: references
|
||||||
|
attributes:
|
||||||
|
label: References
|
||||||
|
description: Any papers, documentation or other materials related to this documentation task
|
||||||
|
placeholder: |
|
||||||
|
- Smith et al. (2022). "Best practices in machine learning documentation"
|
||||||
|
- Code in src/preprocessing/normalize.py
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: notes
|
||||||
|
attributes:
|
||||||
|
label: Additional Notes
|
||||||
|
description: Any other relevant information
|
||||||
|
placeholder: This documentation will be referenced in Chapter 3 of the thesis
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
124
.github/ISSUE_TEMPLATE/experiment.yml
vendored
Normal file
124
.github/ISSUE_TEMPLATE/experiment.yml
vendored
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
# .github/ISSUE_TEMPLATE/experiment.yml
|
||||||
|
name: Experiment
|
||||||
|
description: Document a new ML experiment
|
||||||
|
title: "[EXP] "
|
||||||
|
labels: ["experiment"]
|
||||||
|
assignees:
|
||||||
|
- ${{github.actor}}
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
Use this template to document a new experiment for your thesis.
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: hypothesis
|
||||||
|
attributes:
|
||||||
|
label: Hypothesis
|
||||||
|
description: What is the hypothesis you're testing with this experiment?
|
||||||
|
placeholder: Using a deeper network with residual connections will improve accuracy on the imbalanced dataset without increasing overfitting
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: background
|
||||||
|
attributes:
|
||||||
|
label: Background & Motivation
|
||||||
|
description: Background context and why this experiment is important
|
||||||
|
placeholder: Previous experiments showed promising results but suffered from overfitting. Recent literature suggests that...
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: dataset
|
||||||
|
attributes:
|
||||||
|
label: Dataset
|
||||||
|
description: What data will you use for this experiment?
|
||||||
|
placeholder: |
|
||||||
|
- Dataset: MNIST with augmentation
|
||||||
|
- Preprocessing: Standardization + random rotation
|
||||||
|
- Train/Test Split: 80/20
|
||||||
|
- Validation strategy: 5-fold cross-validation
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: methodology
|
||||||
|
attributes:
|
||||||
|
label: Methodology
|
||||||
|
description: How will you conduct the experiment?
|
||||||
|
placeholder: |
|
||||||
|
1. Implement ResNet architecture with varying depths (18, 34, 50)
|
||||||
|
2. Train with early stopping (patience=10)
|
||||||
|
3. Compare against baseline CNN from experiment #23
|
||||||
|
4. Analyze learning curves and performance metrics
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: parameters
|
||||||
|
attributes:
|
||||||
|
label: Parameters & Hyperparameters
|
||||||
|
description: List the key parameters for this experiment
|
||||||
|
placeholder: |
|
||||||
|
- Learning rate: 0.001 with Adam optimizer
|
||||||
|
- Batch size: 64
|
||||||
|
- Epochs: Max 100 with early stopping
|
||||||
|
- Dropout rate: 0.3
|
||||||
|
- L2 regularization: 1e-4
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: metrics
|
||||||
|
attributes:
|
||||||
|
label: Evaluation Metrics
|
||||||
|
description: How will you evaluate the results?
|
||||||
|
placeholder: |
|
||||||
|
- Accuracy
|
||||||
|
- F1-score (macro-averaged)
|
||||||
|
- ROC-AUC
|
||||||
|
- Training vs. validation loss curves
|
||||||
|
- Inference time
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: input
|
||||||
|
id: notebook
|
||||||
|
attributes:
|
||||||
|
label: Notebook Location
|
||||||
|
description: Where will the experiment notebook be stored?
|
||||||
|
placeholder: notebooks/experiment_resnet_comparison.ipynb
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: dependencies
|
||||||
|
attributes:
|
||||||
|
label: Dependencies
|
||||||
|
description: What other issues or tasks does this experiment depend on?
|
||||||
|
placeholder: |
|
||||||
|
- Depends on issue #42 (Data preprocessing pipeline)
|
||||||
|
- Requires completion of issue #51 (Baseline model)
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: references
|
||||||
|
attributes:
|
||||||
|
label: References
|
||||||
|
description: Any papers, documentation or other materials relevant to this experiment
|
||||||
|
placeholder: |
|
||||||
|
- He et al. (2016). "Deep Residual Learning for Image Recognition"
|
||||||
|
- My previous experiment #23 (baseline CNN)
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: notes
|
||||||
|
attributes:
|
||||||
|
label: Additional Notes
|
||||||
|
description: Any other relevant information
|
||||||
|
placeholder: This experiment may require significant GPU resources. Expected runtime is ~3 hours on Tesla V100.
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
99
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
Normal file
99
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
# .github/ISSUE_TEMPLATE/feature_request.yml
|
||||||
|
name: Feature Request
|
||||||
|
description: Suggest a new feature or enhancement
|
||||||
|
title: "[FEAT] "
|
||||||
|
labels: ["enhancement"]
|
||||||
|
assignees:
|
||||||
|
- ${{github.actor}}
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
Thanks for taking the time to propose a new feature!
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: problem
|
||||||
|
attributes:
|
||||||
|
label: Problem Statement
|
||||||
|
description: What problem are you trying to solve with this feature?
|
||||||
|
placeholder: I'm frustrated when trying to analyze different model results because I need to manually compare them...
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: solution
|
||||||
|
attributes:
|
||||||
|
label: Proposed Solution
|
||||||
|
description: Describe the solution you'd like to implement
|
||||||
|
placeholder: Create a visualization utility that automatically compares results across multiple models and experiments
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: alternatives
|
||||||
|
attributes:
|
||||||
|
label: Alternatives Considered
|
||||||
|
description: Describe alternatives you've considered
|
||||||
|
placeholder: I considered using an external tool, but integrating directly would provide better workflow
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
|
||||||
|
- type: dropdown
|
||||||
|
id: component
|
||||||
|
attributes:
|
||||||
|
label: Component
|
||||||
|
description: Which part of the thesis project would this feature affect?
|
||||||
|
options:
|
||||||
|
- LaTeX Document
|
||||||
|
- Python Source Code
|
||||||
|
- Jupyter Notebook
|
||||||
|
- Data Processing
|
||||||
|
- ML Model
|
||||||
|
- Visualization
|
||||||
|
- Build/Environment
|
||||||
|
- Multiple Components
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: dropdown
|
||||||
|
id: priority
|
||||||
|
attributes:
|
||||||
|
label: Priority
|
||||||
|
description: How important is this feature for your thesis progression?
|
||||||
|
options:
|
||||||
|
- Critical (blocks progress)
|
||||||
|
- High (significantly improves workflow)
|
||||||
|
- Medium (nice to have)
|
||||||
|
- Low (minor improvement)
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: implementation
|
||||||
|
attributes:
|
||||||
|
label: Implementation Ideas
|
||||||
|
description: Any initial thoughts on how to implement this feature?
|
||||||
|
placeholder: |
|
||||||
|
- Could use matplotlib's subplot feature
|
||||||
|
- Would need to standardize the model output format
|
||||||
|
- Should include statistical significance tests
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: benefits
|
||||||
|
attributes:
|
||||||
|
label: Expected Benefits
|
||||||
|
description: How will this feature benefit your thesis work?
|
||||||
|
placeholder: This will save time in analysis and provide more consistent comparisons across experiments
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: additional
|
||||||
|
attributes:
|
||||||
|
label: Additional Context
|
||||||
|
description: Any other context, screenshots, or reference material
|
||||||
|
placeholder: Here's a paper that uses a similar approach...
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,4 +1,4 @@
|
|||||||
# Ignore CSV files in the data directory and all its subdirectories
|
# Ignore CSV files in the data directory and all its subdirectories
|
||||||
data/**/*.csv
|
data/**/*.csv
|
||||||
|
.venv/
|
||||||
*.pyc
|
*.pyc
|
||||||
30
.gitmessage
Normal file
30
.gitmessage
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
# .gitmessage
|
||||||
|
|
||||||
|
# <type>(<scope>): <subject>
|
||||||
|
# |<---- Using a Maximum Of 50 Characters ---->|
|
||||||
|
#
|
||||||
|
# Explain the problem that this commit is solving. Focus on why you
|
||||||
|
# are making this change as opposed to how. Use clear, concise language.
|
||||||
|
# |<---- Try To Limit Each Line to a Maximum Of 72 Characters ---->|
|
||||||
|
#
|
||||||
|
# -- COMMIT END --
|
||||||
|
# Types:
|
||||||
|
# feat (new feature)
|
||||||
|
# fix (bug fix)
|
||||||
|
# refactor (refactoring code)
|
||||||
|
# style (formatting, no code change)
|
||||||
|
# doc (changes to documentation)
|
||||||
|
# test (adding or refactoring tests)
|
||||||
|
# perf (performance improvements)
|
||||||
|
# chore (routine tasks, dependencies)
|
||||||
|
# exp (experimental work/exploration)
|
||||||
|
#
|
||||||
|
# Scope:
|
||||||
|
# latex (changes to thesis LaTeX)
|
||||||
|
# src (changes to Python source code)
|
||||||
|
# nb (changes to notebooks)
|
||||||
|
# ml (ML model specific changes)
|
||||||
|
# data (data processing/preparation)
|
||||||
|
# viz (visualization related)
|
||||||
|
# all (changes spanning entire repository)
|
||||||
|
# --------------------
|
||||||
7
LICENSE
7
LICENSE
@@ -0,0 +1,7 @@
|
|||||||
|
Copyright 2024 Rifqi D. Panuluh
|
||||||
|
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
This repository is for viewing purposes only. No part of this repository, including but not limited to the code, files, and documentation, may be copied, reproduced, modified, or distributed in any form or by any means without the prior written permission of the copyright holder.
|
||||||
|
|
||||||
|
Unauthorized use, distribution, or modification of this repository may result in legal action.
|
||||||
|
|||||||
18
README.md
18
README.md
@@ -0,0 +1,18 @@
|
|||||||
|
## Summary
|
||||||
|
|
||||||
|
This repository contains the work related to my thesis, which focuses on damage localization prediction. The research explores the application of machine learning techniques to structural health monitoring.
|
||||||
|
|
||||||
|
**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
|
||||||
|
|
||||||
|
- **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)
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
874
code/notebooks/stft.ipynb
Normal file
874
code/notebooks/stft.ipynb
Normal file
@@ -0,0 +1,874 @@
|
|||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"import pandas as pd\n",
|
||||||
|
"import numpy as np\n",
|
||||||
|
"import matplotlib.pyplot as plt"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"sensor1 = pd.read_csv('D:/thesis/data/converted/raw/DAMAGE_1/DAMAGE_1_TEST1_01.csv',sep=',')\n",
|
||||||
|
"sensor2 = pd.read_csv('D:/thesis/data/converted/raw/DAMAGE_1/DAMAGE_1_TEST1_02.csv',sep=',')"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"sensor1.columns"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"df1 = pd.DataFrame()\n",
|
||||||
|
"df1['s1'] = sensor1[sensor1.columns[-1]]\n",
|
||||||
|
"df1['s2'] = sensor2[sensor2.columns[-1]]\n",
|
||||||
|
"df1\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"def merge_two_sensors(damage_path, damage):\n",
|
||||||
|
" df = pd.DataFrame()\n",
|
||||||
|
" for file in os.listdir(damage_path):\n",
|
||||||
|
" pattern = re.compile(r'DAMAGE_\\d+_TEST\\d+_\\d{2}\\.csv')\n",
|
||||||
|
" try:\n",
|
||||||
|
" assert pattern.match(file), f\"File {file} does not match the required format, skipping...\"\n",
|
||||||
|
" # assert \"TEST01\" in file, f\"File {file} does not contain 'TEST01', skipping...\" #TODO: should be trained using the whole test file\n",
|
||||||
|
" print(f\"Processing file: {file}\")\n",
|
||||||
|
" # Append the full path of the file to sensor1 or sensor2 based on the filename\n",
|
||||||
|
" if file.endswith('_01.csv'):\n",
|
||||||
|
" df['sensor 1'] = pd.read_csv(os.path.join('D:/thesis/data/converted/raw', damage, file), sep=',', usecols=[1])\n",
|
||||||
|
" elif file.endswith('_02.csv'):\n",
|
||||||
|
" df['sensor 2'] = pd.read_csv(os.path.join('D:/thesis/data/converted/raw', damage, file), sep=',', usecols=[1])\n",
|
||||||
|
" except AssertionError as e:\n",
|
||||||
|
" print(e)\n",
|
||||||
|
" continue # Skip to the next iteration\n",
|
||||||
|
" return df"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"import os\n",
|
||||||
|
"import re\n",
|
||||||
|
"\n",
|
||||||
|
"df = []\n",
|
||||||
|
"for damage in os.listdir('D:/thesis/data/converted/raw'):\n",
|
||||||
|
" damage_path = os.path.join('D:/thesis/data/converted/raw', damage)\n",
|
||||||
|
" df.append(merge_two_sensors(damage_path, damage))\n",
|
||||||
|
" "
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"len(df)\n",
|
||||||
|
"df"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Combined Plot for sensor 1 and sensor 2 from data1 file in which motor is operated at 800 rpm\n",
|
||||||
|
"\n",
|
||||||
|
"plt.plot(df1['s2'], label='sensor 2')\n",
|
||||||
|
"plt.plot(df1['s1'], label='sensor 1', alpha=0.5)\n",
|
||||||
|
"plt.xlabel(\"Number of samples\")\n",
|
||||||
|
"plt.ylabel(\"Amplitude\")\n",
|
||||||
|
"plt.title(\"Raw vibration signal\")\n",
|
||||||
|
"plt.ylim(-7.5, 5)\n",
|
||||||
|
"plt.legend()\n",
|
||||||
|
"plt.show()"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"signal_sensor1_test1 = []\n",
|
||||||
|
"signal_sensor2_test1 = []\n",
|
||||||
|
"\n",
|
||||||
|
"for data in df:\n",
|
||||||
|
" signal_sensor1_test1.append(data['sensor 1'].values)\n",
|
||||||
|
" signal_sensor2_test1.append(data['sensor 2'].values)\n",
|
||||||
|
"\n",
|
||||||
|
"print(len(signal_sensor1_test1))\n",
|
||||||
|
"print(len(signal_sensor2_test1))"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## Applying Short-Time Fourier Transform (STFT)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"os.getcwd()"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"import os\n",
|
||||||
|
"import pandas as pd\n",
|
||||||
|
"import numpy as np\n",
|
||||||
|
"from scipy.signal import stft, hann\n",
|
||||||
|
"from multiprocessing import Pool\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"# Function to compute and append STFT data\n",
|
||||||
|
"def process_stft(args):\n",
|
||||||
|
" # Define STFT parameters\n",
|
||||||
|
" window_size = 1024\n",
|
||||||
|
" hop_size = 512\n",
|
||||||
|
" window = hann(window_size)\n",
|
||||||
|
"\n",
|
||||||
|
" Fs = 1024 # Sampling frequency in Hz\n",
|
||||||
|
" \n",
|
||||||
|
" damage_num, test_num, sensor_suffix = args\n",
|
||||||
|
" sensor_name = active_sensors[sensor_suffix]\n",
|
||||||
|
" sensor_num = sensor_suffix[-1] # '1' or '2'\n",
|
||||||
|
" \n",
|
||||||
|
" # Construct the file path\n",
|
||||||
|
" file_name = f'DAMAGE_{damage_num}_TEST{test_num}_{sensor_suffix}.csv'\n",
|
||||||
|
" file_path = os.path.join(damage_base_path, f'DAMAGE_{damage_num}', file_name)\n",
|
||||||
|
" \n",
|
||||||
|
" # Check if the file exists\n",
|
||||||
|
" if not os.path.isfile(file_path):\n",
|
||||||
|
" print(f\"File {file_path} does not exist. Skipping...\")\n",
|
||||||
|
" return\n",
|
||||||
|
" \n",
|
||||||
|
" # Read the CSV\n",
|
||||||
|
" try:\n",
|
||||||
|
" df = pd.read_csv(file_path)\n",
|
||||||
|
" except Exception as e:\n",
|
||||||
|
" print(f\"Error reading {file_path}: {e}. Skipping...\")\n",
|
||||||
|
" return\n",
|
||||||
|
" \n",
|
||||||
|
" # Ensure the CSV has exactly two columns\n",
|
||||||
|
" if df.shape[1] != 2:\n",
|
||||||
|
" print(f\"Unexpected number of columns in {file_path}. Skipping...\")\n",
|
||||||
|
" return\n",
|
||||||
|
" \n",
|
||||||
|
" # Extract sensor data\n",
|
||||||
|
" sensor_column = df.columns[1]\n",
|
||||||
|
" sensor_data = df[sensor_column].values\n",
|
||||||
|
" \n",
|
||||||
|
" # Compute STFT\n",
|
||||||
|
" frequencies, times, Zxx = stft(sensor_data, fs=Fs, window=window, nperseg=window_size, noverlap=window_size - hop_size)\n",
|
||||||
|
" magnitude = np.abs(Zxx)\n",
|
||||||
|
" flattened_stft = magnitude.flatten()\n",
|
||||||
|
" \n",
|
||||||
|
" # Define the output CSV file path\n",
|
||||||
|
" stft_file_name = f'stft_data{sensor_num}_{damage_num}.csv'\n",
|
||||||
|
" sensor_output_dir = os.path.join(damage_base_path, sensor_name.lower())\n",
|
||||||
|
" os.makedirs(sensor_output_dir, exist_ok=True)\n",
|
||||||
|
" stft_file_path = os.path.join(sensor_output_dir, stft_file_name)\n",
|
||||||
|
" print(stft_file_path)\n",
|
||||||
|
" # Append the flattened STFT to the CSV\n",
|
||||||
|
" try:\n",
|
||||||
|
" flattened_stft_df = pd.DataFrame([flattened_stft])\n",
|
||||||
|
" if not os.path.isfile(stft_file_path):\n",
|
||||||
|
" # Create a new CSV\n",
|
||||||
|
" flattened_stft_df.to_csv(stft_file_path, index=False, header=False)\n",
|
||||||
|
" else:\n",
|
||||||
|
" # Append to existing CSV\n",
|
||||||
|
" flattened_stft_df.to_csv(stft_file_path, mode='a', index=False, header=False)\n",
|
||||||
|
" print(f\"Appended STFT data to {stft_file_path}\")\n",
|
||||||
|
" except Exception as e:\n",
|
||||||
|
" print(f\"Error writing to {stft_file_path}: {e}\")"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Define the base path where DAMAGE_X folders are located\n",
|
||||||
|
"damage_base_path = 'D:/thesis/data/converted/raw/'\n",
|
||||||
|
"\n",
|
||||||
|
"# Define active sensors\n",
|
||||||
|
"active_sensors = {\n",
|
||||||
|
" '01': 'sensor1', # Beginning map sensor\n",
|
||||||
|
" '02': 'sensor2' # End map sensor\n",
|
||||||
|
"}\n",
|
||||||
|
"\n",
|
||||||
|
"# Define damage cases and test runs\n",
|
||||||
|
"damage_cases = range(1, 7) # Adjust based on actual number of damage cases\n",
|
||||||
|
"test_runs = range(1, 6) # TEST01 to TEST05\n",
|
||||||
|
"args_list = []\n",
|
||||||
|
"\n",
|
||||||
|
"# Prepare the list of arguments for parallel processing\n",
|
||||||
|
"for damage_num in damage_cases:\n",
|
||||||
|
" for test_num in test_runs:\n",
|
||||||
|
" for sensor_suffix in active_sensors.keys():\n",
|
||||||
|
" args_list.append((damage_num, test_num, sensor_suffix))\n",
|
||||||
|
"\n",
|
||||||
|
"print(len(args_list))\n",
|
||||||
|
"args_list"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Process STFTs sequentially instead of in parallel\n",
|
||||||
|
"if __name__ == \"__main__\":\n",
|
||||||
|
" print(f\"Starting sequential STFT processing...\")\n",
|
||||||
|
" for i, arg in enumerate(args_list, 1):\n",
|
||||||
|
" process_stft(arg)\n",
|
||||||
|
" print(f\"Processed {i}/{len(args_list)} files\")\n",
|
||||||
|
" print(\"STFT processing completed.\")"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"from scipy.signal import stft, hann\n",
|
||||||
|
"\n",
|
||||||
|
"# Applying STFT\n",
|
||||||
|
"vibration_data = signal_sensor1_test1[1]\n",
|
||||||
|
"window_size = 1024\n",
|
||||||
|
"hop_size = 512\n",
|
||||||
|
"window = hann(window_size) # Creating a Hanning window\n",
|
||||||
|
"Fs = 1024\n",
|
||||||
|
"\n",
|
||||||
|
"frequencies, times, Zxx = stft(vibration_data, \n",
|
||||||
|
" fs=Fs, \n",
|
||||||
|
" window=window, \n",
|
||||||
|
" nperseg=window_size, \n",
|
||||||
|
" noverlap=window_size - hop_size)\n",
|
||||||
|
"# Plotting the STFT Data\n",
|
||||||
|
"plt.pcolormesh(times, frequencies, np.abs(Zxx), shading='gouraud')\n",
|
||||||
|
"plt.title(f'STFT Magnitude for case {1} signal sensor 2')\n",
|
||||||
|
"plt.ylabel(f'Frequency [Hz]')\n",
|
||||||
|
"plt.xlabel(f'Time [sec]')\n",
|
||||||
|
"plt.show()\n",
|
||||||
|
"\n",
|
||||||
|
"# get current y ticks in list\n",
|
||||||
|
"print(len(frequencies))\n",
|
||||||
|
"print(len(times))\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## Loading STFT Data from CSV Files"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"import os\n",
|
||||||
|
"os.listdir('D:/thesis/data/working')"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"import pandas as pd\n",
|
||||||
|
"import matplotlib.pyplot as plt\n",
|
||||||
|
"ready_data1 = []\n",
|
||||||
|
"for file in os.listdir('D:/thesis/data/converted/raw/sensor1'):\n",
|
||||||
|
" ready_data1.append(pd.read_csv(os.path.join('D:/thesis/data/converted/raw/sensor1', file)))\n",
|
||||||
|
"ready_data1[0]\n",
|
||||||
|
"# colormesh give title x is frequency and y is time and rotate/transpose the data\n",
|
||||||
|
"# Plotting the STFT Data"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"ready_data1[1]\n",
|
||||||
|
"plt.pcolormesh(ready_data1[1])"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"for i in range(6):\n",
|
||||||
|
" plt.pcolormesh(ready_data1[i])\n",
|
||||||
|
" plt.title(f'STFT Magnitude for case {i} sensor 1')\n",
|
||||||
|
" plt.xlabel(f'Frequency [Hz]')\n",
|
||||||
|
" plt.ylabel(f'Time [sec]')\n",
|
||||||
|
" plt.show()"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"ready_data2 = []\n",
|
||||||
|
"for file in os.listdir('D:/thesis/data/converted/raw/sensor2'):\n",
|
||||||
|
" ready_data2.append(pd.read_csv(os.path.join('D:/thesis/data/converted/raw/sensor2', file)))\n",
|
||||||
|
"ready_data2[5]"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"print(len(ready_data1))\n",
|
||||||
|
"print(len(ready_data2))"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"x1 = 0\n",
|
||||||
|
"\n",
|
||||||
|
"for i in range(len(ready_data1)):\n",
|
||||||
|
" print(ready_data1[i].shape)\n",
|
||||||
|
" x1 = x1 + ready_data1[i].shape[0]\n",
|
||||||
|
"\n",
|
||||||
|
"print(x1)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"x2 = 0\n",
|
||||||
|
"\n",
|
||||||
|
"for i in range(len(ready_data2)):\n",
|
||||||
|
" print(ready_data2[i].shape)\n",
|
||||||
|
" x2 = x2 + ready_data2[i].shape[0]\n",
|
||||||
|
"\n",
|
||||||
|
"print(x2)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"### Appending"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"x1 = ready_data1[0]\n",
|
||||||
|
"# print(x1)\n",
|
||||||
|
"print(type(x1))\n",
|
||||||
|
"for i in range(len(ready_data1) - 1):\n",
|
||||||
|
" #print(i)\n",
|
||||||
|
" x1 = np.concatenate((x1, ready_data1[i + 1]), axis=0)\n",
|
||||||
|
"# print(x1)\n",
|
||||||
|
"pd.DataFrame(x1)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"x2 = ready_data2[0]\n",
|
||||||
|
"\n",
|
||||||
|
"for i in range(len(ready_data2) - 1):\n",
|
||||||
|
" #print(i)\n",
|
||||||
|
" x2 = np.concatenate((x2, ready_data2[i + 1]), axis=0)\n",
|
||||||
|
"pd.DataFrame(x2)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"print(x1.shape)\n",
|
||||||
|
"print(x2.shape)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"### Labeling"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"y_1 = 0\n",
|
||||||
|
"y_2 = 1\n",
|
||||||
|
"y_3 = 2\n",
|
||||||
|
"y_4 = 3\n",
|
||||||
|
"y_5 = 4\n",
|
||||||
|
"y_6 = 5"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"y_data = [y_1, y_2, y_3, y_4, y_5, y_6]"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"for i in range(len(y_data)):\n",
|
||||||
|
" print(ready_data1[i].shape[0])"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"for i in range(len(y_data)):\n",
|
||||||
|
" print(ready_data2[i].shape[0])"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"for i in range(len(y_data)):\n",
|
||||||
|
" y_data[i] = [y_data[i]]*ready_data1[i].shape[0]\n",
|
||||||
|
" y_data[i] = np.array(y_data[i])"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# len(y_data[0])\n",
|
||||||
|
"y_data[0]"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"y = y_data[0]\n",
|
||||||
|
"\n",
|
||||||
|
"for i in range(len(y_data) - 1):\n",
|
||||||
|
" #print(i)\n",
|
||||||
|
" y = np.concatenate((y, y_data[i+1]), axis=0)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"print(y.shape)\n",
|
||||||
|
"print(np.unique(y))"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"from sklearn.model_selection import train_test_split\n",
|
||||||
|
"\n",
|
||||||
|
"x_train1, x_test1, y_train, y_test = train_test_split(x1, y, test_size=0.2, random_state=2)\n",
|
||||||
|
"x_train2, x_test2, y_train, y_test = train_test_split(x2, y, test_size=0.2, random_state=2)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"from sklearn.model_selection import train_test_split\n",
|
||||||
|
"from sklearn.metrics import accuracy_score\n",
|
||||||
|
"from sklearn.ensemble import RandomForestClassifier, BaggingClassifier\n",
|
||||||
|
"from sklearn.tree import DecisionTreeClassifier\n",
|
||||||
|
"from sklearn.neighbors import KNeighborsClassifier\n",
|
||||||
|
"from sklearn.discriminant_analysis import LinearDiscriminantAnalysis\n",
|
||||||
|
"from sklearn.svm import SVC\n",
|
||||||
|
"from xgboost import XGBClassifier"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Check the shapes of x_train and y_train\n",
|
||||||
|
"print(\"Shape of x1_train:\", x_train1.shape)\n",
|
||||||
|
"print(\"Shape of x2_train:\", x_train2.shape)\n",
|
||||||
|
"print(\"Shape of y_train:\", y_train.shape)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"accuracies1 = []\n",
|
||||||
|
"accuracies2 = []\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"# 1. Random Forest\n",
|
||||||
|
"rf_model = RandomForestClassifier()\n",
|
||||||
|
"rf_model.fit(x_train1, y_train)\n",
|
||||||
|
"rf_pred1 = rf_model.predict(x_test1)\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_model.fit(x_train2, y_train)\n",
|
||||||
|
"rf_pred2 = rf_model.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_model = BaggingClassifier(estimator=DecisionTreeClassifier(), n_estimators=10)\n",
|
||||||
|
"bagged_model.fit(x_train1, y_train)\n",
|
||||||
|
"bagged_pred1 = bagged_model.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_model.fit(x_train2, y_train)\n",
|
||||||
|
"bagged_pred2 = bagged_model.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_model.fit(x_train2, y_train)\n",
|
||||||
|
"dt_pred2 = dt_model.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_model.fit(x_train2, y_train)\n",
|
||||||
|
"knn_pred2 = knn_model.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_model.fit(x_train2, y_train)\n",
|
||||||
|
"lda_pred2 = lda_model.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_model.fit(x_train2, y_train)\n",
|
||||||
|
"svm_pred2 = svm_model.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_model.fit(x_train2, y_train)\n",
|
||||||
|
"xgboost_pred2 = xgboost_model.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)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"print(accuracies1)\n",
|
||||||
|
"print(accuracies2)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"import numpy as np\n",
|
||||||
|
"import matplotlib.pyplot as plt\n",
|
||||||
|
"\n",
|
||||||
|
"models = [rf_model, bagged_model, dt_model, knn_model, lda_model, svm_model, xgboost_model]\n",
|
||||||
|
"model_names = [\"Random Forest\", \"Bagged Trees\", \"Decision Tree\", \"KNN\", \"LDA\", \"SVM\", \"XGBoost\"]\n",
|
||||||
|
"\n",
|
||||||
|
"bar_width = 0.35 # Width of each bar\n",
|
||||||
|
"index = np.arange(len(model_names)) # Index for the bars\n",
|
||||||
|
"\n",
|
||||||
|
"# Plotting the bar graph\n",
|
||||||
|
"plt.figure(figsize=(14, 8))\n",
|
||||||
|
"\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"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"import pandas as pd\n",
|
||||||
|
"import numpy as np\n",
|
||||||
|
"import os\n",
|
||||||
|
"import matplotlib.pyplot as plt"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"def spectograph(data_dir: str):\n",
|
||||||
|
" # print(os.listdir(data_dir))\n",
|
||||||
|
" for damage in os.listdir(data_dir):\n",
|
||||||
|
" # print(damage)\n",
|
||||||
|
" d = os.path.join(data_dir, damage)\n",
|
||||||
|
" # print(d)\n",
|
||||||
|
" for file in os.listdir(d):\n",
|
||||||
|
" # print(file)\n",
|
||||||
|
" f = os.path.join(d, file)\n",
|
||||||
|
" print(f)\n",
|
||||||
|
" # sensor1 = pd.read_csv(f, skiprows=1, sep=';')\n",
|
||||||
|
" # sensor2 = pd.read_csv(f, skiprows=1, sep=';')\n",
|
||||||
|
"\n",
|
||||||
|
" # df1 = pd.DataFrame()\n",
|
||||||
|
"\n",
|
||||||
|
" # df1['s1'] = sensor1[sensor1.columns[-1]]\n",
|
||||||
|
" # df1['s2'] = sensor2[sensor2.columns[-1]]\n",
|
||||||
|
" # # Combined Plot for sensor 1 and sensor 2 from data1 file in which motor is operated at 800 rpm\n",
|
||||||
|
"\n",
|
||||||
|
" # plt.plot(df1['s2'], label='sensor 2')\n",
|
||||||
|
" # plt.plot(df1['s1'], label='sensor 1')\n",
|
||||||
|
" # plt.xlabel(\"Number of samples\")\n",
|
||||||
|
" # plt.ylabel(\"Amplitude\")\n",
|
||||||
|
" # plt.title(\"Raw vibration signal\")\n",
|
||||||
|
" # plt.legend()\n",
|
||||||
|
" # plt.show()\n",
|
||||||
|
"\n",
|
||||||
|
" # from scipy import signal\n",
|
||||||
|
" # from scipy.signal.windows import hann\n",
|
||||||
|
"\n",
|
||||||
|
" # vibration_data = df1['s1']\n",
|
||||||
|
"\n",
|
||||||
|
" # # Applying STFT\n",
|
||||||
|
" # window_size = 1024\n",
|
||||||
|
" # hop_size = 512\n",
|
||||||
|
" # window = hann(window_size) # Creating a Hanning window\n",
|
||||||
|
" # frequencies, times, Zxx = signal.stft(vibration_data, window=window, nperseg=window_size, noverlap=window_size - hop_size)\n",
|
||||||
|
"\n",
|
||||||
|
" # # Plotting the STFT Data\n",
|
||||||
|
" # plt.pcolormesh(times, frequencies, np.abs(Zxx), shading='gouraud')\n",
|
||||||
|
" # plt.title(f'STFT Magnitude for case 1 signal sensor 1 ')\n",
|
||||||
|
" # plt.ylabel('Frequency [Hz]')\n",
|
||||||
|
" # plt.xlabel('Time [sec]')\n",
|
||||||
|
" # plt.show()"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## Test with Outside of Its Training Data"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "Python 3",
|
||||||
|
"language": "python",
|
||||||
|
"name": "python3"
|
||||||
|
},
|
||||||
|
"language_info": {
|
||||||
|
"codemirror_mode": {
|
||||||
|
"name": "ipython",
|
||||||
|
"version": 3
|
||||||
|
},
|
||||||
|
"file_extension": ".py",
|
||||||
|
"mimetype": "text/x-python",
|
||||||
|
"name": "python",
|
||||||
|
"nbconvert_exporter": "python",
|
||||||
|
"pygments_lexer": "ipython3",
|
||||||
|
"version": "3.10.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 2
|
||||||
|
}
|
||||||
192
code/src/features/frequency_domain_features.py
Normal file
192
code/src/features/frequency_domain_features.py
Normal file
@@ -0,0 +1,192 @@
|
|||||||
|
import numpy as np
|
||||||
|
import pandas as pd
|
||||||
|
from scipy.fft import fft, fftfreq
|
||||||
|
|
||||||
|
def get_mean_freq(signal, frame_size, hop_length):
|
||||||
|
mean = []
|
||||||
|
for i in range(0, len(signal), hop_length):
|
||||||
|
L = len(signal[i:i+frame_size])
|
||||||
|
y = abs(np.fft.fft(signal[i:i+frame_size]/L))[:int(L/2)]
|
||||||
|
current_mean = np.sum(y)/frame_size
|
||||||
|
mean.append(current_mean)
|
||||||
|
return np.array(mean)
|
||||||
|
|
||||||
|
def get_variance_freq(signal, frame_size, hop_length):
|
||||||
|
var = []
|
||||||
|
for i in range(0, len(signal), hop_length):
|
||||||
|
L = len(signal[i:i+frame_size])
|
||||||
|
y = abs(np.fft.fft(signal[i:i+frame_size]/L))[:int(L/2)]
|
||||||
|
current_var = (np.sum((y - (np.sum(y)/frame_size))**2))/(frame_size-1)
|
||||||
|
var.append(current_var)
|
||||||
|
return np.array(var)
|
||||||
|
|
||||||
|
def get_third_freq(signal, frame_size, hop_length):
|
||||||
|
third = []
|
||||||
|
for i in range(0, len(signal), hop_length):
|
||||||
|
L = len(signal[i:i+frame_size])
|
||||||
|
y = abs(np.fft.fft(signal[i:i+frame_size]/L))[:int(L/2)]
|
||||||
|
current_third = (np.sum((y - (np.sum(y)/frame_size))**3))/(frame_size * (np.sqrt((np.sum((y - (np.sum(y)/frame_size))**2))/(frame_size-1)))**3)
|
||||||
|
third.append(current_third)
|
||||||
|
return np.array(third)
|
||||||
|
|
||||||
|
def get_forth_freq(signal, frame_size, hop_length):
|
||||||
|
forth = []
|
||||||
|
for i in range(0, len(signal), hop_length):
|
||||||
|
L = len(signal[i:i+frame_size])
|
||||||
|
y = abs(np.fft.fft(signal[i:i+frame_size]/L))[:int(L/2)]
|
||||||
|
current_forth = (np.sum((y - (np.sum(y)/frame_size))**4))/(frame_size * ((np.sum((y - (np.sum(y)/frame_size))**2))/(frame_size-1))**2)
|
||||||
|
forth.append(current_forth)
|
||||||
|
return np.array(forth)
|
||||||
|
|
||||||
|
def get_grand_freq(signal, frame_size, hop_length):
|
||||||
|
grand = []
|
||||||
|
for i in range(0, len(signal), hop_length):
|
||||||
|
L = len(signal[i:i+frame_size])
|
||||||
|
y = abs(np.fft.fft(signal[i:i+frame_size]/L))[:int(L/2)]
|
||||||
|
f = np.fft.fftfreq (L,.1/25600)[:int(L/2)]
|
||||||
|
current_grand = np.sum(f * y)/np.sum(y)
|
||||||
|
grand.append(current_grand)
|
||||||
|
return np.array(grand)
|
||||||
|
|
||||||
|
def get_std_freq(signal, frame_size, hop_length):
|
||||||
|
std = []
|
||||||
|
for i in range(0, len(signal), hop_length):
|
||||||
|
L = len(signal[i:i+frame_size])
|
||||||
|
y = abs(np.fft.fft(signal[i:i+frame_size]/L))[:int(L/2)]
|
||||||
|
f = np.fft.fftfreq (L,.1/25600)[:int(L/2)]
|
||||||
|
current_std = np.sqrt(np.sum((f-(np.sum(f * y)/np.sum(y)))**2 * y)/frame_size)
|
||||||
|
std.append(current_std)
|
||||||
|
return np.array(std)
|
||||||
|
|
||||||
|
def get_Cfactor_freq(signal, frame_size, hop_length):
|
||||||
|
cfactor = []
|
||||||
|
for i in range(0, len(signal), hop_length):
|
||||||
|
L = len(signal[i:i+frame_size])
|
||||||
|
y = abs(np.fft.fft(signal[i:i+frame_size]/L))[:int(L/2)]
|
||||||
|
f = np.fft.fftfreq (L,.1/25600)[:int(L/2)]
|
||||||
|
current_cfactor = np.sqrt(np.sum(f**2 * y)/np.sum(y))
|
||||||
|
cfactor.append(current_cfactor)
|
||||||
|
return np.array(cfactor)
|
||||||
|
|
||||||
|
def get_Dfactor_freq(signal, frame_size, hop_length):
|
||||||
|
dfactor = []
|
||||||
|
for i in range(0, len(signal), hop_length):
|
||||||
|
L = len(signal[i:i+frame_size])
|
||||||
|
y = abs(np.fft.fft(signal[i:i+frame_size]/L))[:int(L/2)]
|
||||||
|
f = np.fft.fftfreq (L,.1/25600)[:int(L/2)]
|
||||||
|
current_dfactor = np.sqrt(np.sum(f**4 * y)/np.sum(f**2 * y))
|
||||||
|
dfactor.append(current_dfactor)
|
||||||
|
return np.array(dfactor)
|
||||||
|
|
||||||
|
def get_Efactor_freq(signal, frame_size, hop_length):
|
||||||
|
efactor = []
|
||||||
|
for i in range(0, len(signal), hop_length):
|
||||||
|
L = len(signal[i:i+frame_size])
|
||||||
|
y = abs(np.fft.fft(signal[i:i+frame_size]/L))[:int(L/2)]
|
||||||
|
f = np.fft.fftfreq (L,.1/25600)[:int(L/2)]
|
||||||
|
current_efactor = np.sqrt(np.sum(f**2 * y)/np.sqrt(np.sum(y) * np.sum(f**4 * y)))
|
||||||
|
efactor.append(current_efactor)
|
||||||
|
return np.array(efactor)
|
||||||
|
|
||||||
|
def get_Gfactor_freq(signal, frame_size, hop_length):
|
||||||
|
gfactor = []
|
||||||
|
for i in range(0, len(signal), hop_length):
|
||||||
|
L = len(signal[i:i+frame_size])
|
||||||
|
y = abs(np.fft.fft(signal[i:i+frame_size]/L))[:int(L/2)]
|
||||||
|
f = np.fft.fftfreq (L,.1/25600)[:int(L/2)]
|
||||||
|
current_gfactor = (np.sqrt(np.sum((f-(np.sum(f * y)/np.sum(y)))**2 * y)/frame_size))/(np.sum(f * y)/np.sum(y))
|
||||||
|
gfactor.append(current_gfactor)
|
||||||
|
return np.array(gfactor)
|
||||||
|
|
||||||
|
def get_third1_freq(signal, frame_size, hop_length):
|
||||||
|
third1 = []
|
||||||
|
for i in range(0, len(signal), hop_length):
|
||||||
|
L = len(signal[i:i+frame_size])
|
||||||
|
y = abs(np.fft.fft(signal[i:i+frame_size]/L))[:int(L/2)]
|
||||||
|
f = np.fft.fftfreq (L,.1/25600)[:int(L/2)]
|
||||||
|
current_third1 = np.sum((f - (np.sum(f * y)/np.sum(y)))**3 * y)/(frame_size * (np.sqrt(np.sum((f-(np.sum(f * y)/np.sum(y)))**2 * y)/frame_size))**3)
|
||||||
|
third1.append(current_third1)
|
||||||
|
return np.array(third1)
|
||||||
|
|
||||||
|
def get_forth1_freq(signal, frame_size, hop_length):
|
||||||
|
forth1 = []
|
||||||
|
for i in range(0, len(signal), hop_length):
|
||||||
|
L = len(signal[i:i+frame_size])
|
||||||
|
y = abs(np.fft.fft(signal[i:i+frame_size]/L))[:int(L/2)]
|
||||||
|
f = np.fft.fftfreq (L,.1/25600)[:int(L/2)]
|
||||||
|
current_forth1 = np.sum((f - (np.sum(f * y)/np.sum(y)))**4 * y)/(frame_size * (np.sqrt(np.sum((f-(np.sum(f * y)/np.sum(y)))**2 * y)/frame_size))**4)
|
||||||
|
forth1.append(current_forth1)
|
||||||
|
return np.array(forth1)
|
||||||
|
|
||||||
|
def get_Hfactor_freq(signal, frame_size, hop_length):
|
||||||
|
hfactor = []
|
||||||
|
for i in range(0, len(signal), hop_length):
|
||||||
|
L = len(signal[i:i+frame_size])
|
||||||
|
y = abs(np.fft.fft(signal[i:i+frame_size]/L))[:int(L/2)]
|
||||||
|
f = np.fft.fftfreq (L,.1/25600)[:int(L/2)]
|
||||||
|
current_hfactor = np.sum(np.sqrt(abs(f - (np.sum(f * y)/np.sum(y)))) * y)/(frame_size * np.sqrt(np.sqrt(np.sum((f-(np.sum(f * y)/np.sum(y)))**2 * y)/frame_size)))
|
||||||
|
hfactor.append(current_hfactor)
|
||||||
|
return np.array(hfactor)
|
||||||
|
|
||||||
|
def get_Jfactor_freq(signal, frame_size, hop_length):
|
||||||
|
jfactor = []
|
||||||
|
for i in range(0, len(signal), hop_length):
|
||||||
|
L = len(signal[i:i+frame_size])
|
||||||
|
y = abs(np.fft.fft(signal[i:i+frame_size]/L))[:int(L/2)]
|
||||||
|
f = np.fft.fftfreq (L,.1/25600)[:int(L/2)]
|
||||||
|
current_jfactor = np.sum(np.sqrt(abs(f - (np.sum(f * y)/np.sum(y)))) * y)/(frame_size * np.sqrt(np.sqrt(np.sum((f-(np.sum(f * y)/np.sum(y)))**2 * y)/frame_size)))
|
||||||
|
jfactor.append(current_jfactor)
|
||||||
|
return np.array(jfactor)
|
||||||
|
|
||||||
|
class FrequencyFeatureExtractor:
|
||||||
|
def __init__(self, data):
|
||||||
|
# Assuming data is a numpy array
|
||||||
|
self.x = data
|
||||||
|
# Perform FFT and compute magnitude of frequency components
|
||||||
|
self.frequency_spectrum = np.abs(fft(self.x))
|
||||||
|
self.n = len(self.frequency_spectrum)
|
||||||
|
self.mean_freq = np.mean(self.frequency_spectrum)
|
||||||
|
self.variance_freq = np.var(self.frequency_spectrum)
|
||||||
|
self.std_freq = np.std(self.frequency_spectrum)
|
||||||
|
|
||||||
|
# Calculate the required frequency features
|
||||||
|
self.features = self.calculate_features()
|
||||||
|
|
||||||
|
def calculate_features(self):
|
||||||
|
S_mu = self.mean_freq
|
||||||
|
S_MAX = np.max(self.frequency_spectrum)
|
||||||
|
S_SBP = np.sum(self.frequency_spectrum)
|
||||||
|
S_Peak = np.max(self.frequency_spectrum)
|
||||||
|
S_V = np.sum((self.frequency_spectrum - S_mu) ** 2) / (self.n - 1)
|
||||||
|
S_Sigma = np.sqrt(S_V)
|
||||||
|
S_Skewness = np.sum((self.frequency_spectrum - S_mu) ** 3) / (self.n * S_Sigma ** 3)
|
||||||
|
S_Kurtosis = np.sum((self.frequency_spectrum - S_mu) ** 4) / (self.n * S_Sigma ** 4)
|
||||||
|
S_RSPPB = S_Peak / S_mu
|
||||||
|
|
||||||
|
return {
|
||||||
|
'Mean of band Power Spectrum (S_mu)': S_mu,
|
||||||
|
'Max of band power spectrum (S_MAX)': S_MAX,
|
||||||
|
'Sum of total band power (S_SBP)': S_SBP,
|
||||||
|
'Peak of band power (S_Peak)': S_Peak,
|
||||||
|
'Variance of band power (S_V)': S_V,
|
||||||
|
'Standard Deviation of band power (S_Sigma)': S_Sigma,
|
||||||
|
'Skewness of band power (S_Skewness)': S_Skewness,
|
||||||
|
'Kurtosis of band power (S_Kurtosis)': S_Kurtosis,
|
||||||
|
'Relative Spectral Peak per Band Power (S_RSPPB)': S_RSPPB
|
||||||
|
}
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
result = "Frequency Domain Feature Extraction Results:\n"
|
||||||
|
for feature, value in self.features.items():
|
||||||
|
result += f"{feature}: {value:.4f}\n"
|
||||||
|
return result
|
||||||
|
|
||||||
|
def ExtractFrequencyFeatures(object):
|
||||||
|
data = pd.read_csv(object, skiprows=1) # Skip the header row separator char info
|
||||||
|
extractor = FrequencyFeatureExtractor(data.iloc[:, 1].values) # Assuming the data is in the second column
|
||||||
|
features = extractor.features
|
||||||
|
return features
|
||||||
|
|
||||||
|
# Usage Example
|
||||||
|
# extractor = FrequencyFeatureExtractor('path_to_your_data.csv')
|
||||||
|
# print(extractor)
|
||||||
@@ -36,9 +36,12 @@ class FeatureExtractor:
|
|||||||
result += f"{feature}: {value:.4f}\n"
|
result += f"{feature}: {value:.4f}\n"
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def ExtractTimeFeatures(object):
|
def ExtractTimeFeatures(object, absolute):
|
||||||
data = pd.read_csv(object, skiprows=1) # Skip the header row separator char info
|
data = pd.read_csv(object, skiprows=1) # Skip the header row separator char info
|
||||||
extractor = FeatureExtractor(data.iloc[:, 1].values) # Assuming the data is in the second column
|
if absolute:
|
||||||
|
extractor = FeatureExtractor(np.abs(data.iloc[:, 1].values)) # Assuming the data is in the second column
|
||||||
|
else:
|
||||||
|
extractor = FeatureExtractor(data.iloc[:, 1].values)
|
||||||
features = extractor.features
|
features = extractor.features
|
||||||
return features
|
return features
|
||||||
# Save features to a file
|
# Save features to a file
|
||||||
|
|||||||
115
code/src/process_stft.py
Normal file
115
code/src/process_stft.py
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
import os
|
||||||
|
import pandas as pd
|
||||||
|
import numpy as np
|
||||||
|
from scipy.signal import stft, hann
|
||||||
|
import glob
|
||||||
|
import multiprocessing # Added import for multiprocessing
|
||||||
|
|
||||||
|
# Define the base directory where DAMAGE_X folders are located
|
||||||
|
damage_base_path = 'D:/thesis/data/converted/raw'
|
||||||
|
|
||||||
|
# Define output directories for each sensor
|
||||||
|
output_dirs = {
|
||||||
|
'sensor1': os.path.join(damage_base_path, 'sensor1'),
|
||||||
|
'sensor2': os.path.join(damage_base_path, 'sensor2')
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create output directories if they don't exist
|
||||||
|
for dir_path in output_dirs.values():
|
||||||
|
os.makedirs(dir_path, exist_ok=True)
|
||||||
|
|
||||||
|
# Define STFT parameters
|
||||||
|
window_size = 1024
|
||||||
|
hop_size = 512
|
||||||
|
window = hann(window_size)
|
||||||
|
Fs = 1024
|
||||||
|
|
||||||
|
# Number of damage cases (adjust as needed)
|
||||||
|
num_damage_cases = 6 # Change to 30 if you have 30 damage cases
|
||||||
|
|
||||||
|
# Number of test runs per damage case
|
||||||
|
num_test_runs = 5
|
||||||
|
|
||||||
|
# Function to perform STFT and return magnitude
|
||||||
|
def compute_stft(vibration_data):
|
||||||
|
frequencies, times, Zxx = stft(
|
||||||
|
vibration_data,
|
||||||
|
fs=Fs,
|
||||||
|
window=window,
|
||||||
|
nperseg=window_size,
|
||||||
|
noverlap=window_size - hop_size
|
||||||
|
)
|
||||||
|
stft_magnitude = np.abs(Zxx)
|
||||||
|
return stft_magnitude.T # Transpose to have frequencies as columns
|
||||||
|
|
||||||
|
def process_damage_case(damage_num):
|
||||||
|
damage_folder = os.path.join(damage_base_path, f'DAMAGE_{damage_num}')
|
||||||
|
|
||||||
|
# Check if the damage folder exists
|
||||||
|
if not os.path.isdir(damage_folder):
|
||||||
|
print(f"Folder {damage_folder} does not exist. Skipping...")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Process Sensor 1 and Sensor 2 separately
|
||||||
|
for sensor_num in [1, 2]:
|
||||||
|
aggregated_stft = [] # List to hold STFTs from all test runs
|
||||||
|
|
||||||
|
# Iterate over all test runs
|
||||||
|
for test_num in range(1, num_test_runs + 1):
|
||||||
|
# Construct the filename based on sensor number
|
||||||
|
# Sensor 1 corresponds to '_01', Sensor 2 corresponds to '_02'
|
||||||
|
sensor_suffix = f'_0{sensor_num}'
|
||||||
|
file_name = f'DAMAGE_{damage_num}_TEST{test_num}{sensor_suffix}.csv'
|
||||||
|
file_path = os.path.join(damage_folder, file_name)
|
||||||
|
|
||||||
|
# Check if the file exists
|
||||||
|
if not os.path.isfile(file_path):
|
||||||
|
print(f"File {file_path} does not exist. Skipping...")
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Read the CSV file
|
||||||
|
try:
|
||||||
|
df = pd.read_csv(file_path)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error reading {file_path}: {e}. Skipping...")
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Ensure the CSV has exactly two columns: 'Timestamp (s)' and 'Sensor X'
|
||||||
|
if df.shape[1] != 2:
|
||||||
|
print(f"Unexpected number of columns in {file_path}. Expected 2, got {df.shape[1]}. Skipping...")
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Extract vibration data (assuming the second column is sensor data)
|
||||||
|
vibration_data = df.iloc[:, 1].values
|
||||||
|
|
||||||
|
# Perform STFT
|
||||||
|
stft_magnitude = compute_stft(vibration_data)
|
||||||
|
|
||||||
|
# Convert STFT result to DataFrame
|
||||||
|
df_stft = pd.DataFrame(
|
||||||
|
stft_magnitude,
|
||||||
|
columns=[f"Freq_{freq:.2f}" for freq in np.linspace(0, Fs/2, stft_magnitude.shape[1])]
|
||||||
|
)
|
||||||
|
|
||||||
|
# Append to the aggregated list
|
||||||
|
aggregated_stft.append(df_stft)
|
||||||
|
|
||||||
|
# Concatenate all STFT DataFrames vertically
|
||||||
|
if aggregated_stft:
|
||||||
|
df_aggregated = pd.concat(aggregated_stft, ignore_index=True)
|
||||||
|
|
||||||
|
# Define output filename
|
||||||
|
output_file = os.path.join(
|
||||||
|
output_dirs[f'sensor{sensor_num}'],
|
||||||
|
f'stft_data{sensor_num}_{damage_num}.csv'
|
||||||
|
)
|
||||||
|
|
||||||
|
# Save the aggregated STFT to CSV
|
||||||
|
df_aggregated.to_csv(output_file, index=False)
|
||||||
|
print(f"Saved aggregated STFT for Sensor {sensor_num}, Damage {damage_num} to {output_file}")
|
||||||
|
else:
|
||||||
|
print(f"No STFT data aggregated for Sensor {sensor_num}, Damage {damage_num}.")
|
||||||
|
|
||||||
|
if __name__ == "__main__": # Added main guard for multiprocessing
|
||||||
|
with multiprocessing.Pool() as pool:
|
||||||
|
pool.map(process_damage_case, range(1, num_damage_cases + 1))
|
||||||
133
code/src/verify_stft.py
Normal file
133
code/src/verify_stft.py
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
import os
|
||||||
|
import pandas as pd
|
||||||
|
import numpy as np
|
||||||
|
from scipy.signal import stft, hann
|
||||||
|
import glob
|
||||||
|
|
||||||
|
# Define the base directory where DAMAGE_X folders are located
|
||||||
|
damage_base_path = 'D:/thesis/data/converted/raw/'
|
||||||
|
|
||||||
|
# Define sensor directories
|
||||||
|
sensor_dirs = {
|
||||||
|
'sensor1': os.path.join(damage_base_path, 'sensor1'),
|
||||||
|
'sensor2': os.path.join(damage_base_path, 'sensor2')
|
||||||
|
}
|
||||||
|
|
||||||
|
# Define STFT parameters
|
||||||
|
window_size = 1024
|
||||||
|
hop_size = 512
|
||||||
|
window = hann(window_size)
|
||||||
|
Fs = 1024
|
||||||
|
|
||||||
|
def verify_stft(damage_num, test_num, sensor_num):
|
||||||
|
"""
|
||||||
|
Verifies the STFT of an individual test run against the aggregated STFT data.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
- damage_num (int): Damage case number.
|
||||||
|
- test_num (int): Test run number.
|
||||||
|
- sensor_num (int): Sensor number (1 or 2).
|
||||||
|
"""
|
||||||
|
# Mapping sensor number to suffix
|
||||||
|
sensor_suffix = f'_0{sensor_num}'
|
||||||
|
|
||||||
|
# Construct the file name for the individual test run
|
||||||
|
individual_file_name = f'DAMAGE_{damage_num}_TEST{test_num}{sensor_suffix}.csv'
|
||||||
|
individual_file_path = os.path.join(damage_base_path, f'DAMAGE_{damage_num}', individual_file_name)
|
||||||
|
|
||||||
|
# Check if the individual file exists
|
||||||
|
if not os.path.isfile(individual_file_path):
|
||||||
|
print(f"File {individual_file_path} does not exist. Skipping verification for this test run.")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Read the individual test run CSV
|
||||||
|
try:
|
||||||
|
df_individual = pd.read_csv(individual_file_path)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error reading {individual_file_path}: {e}. Skipping verification for this test run.")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Ensure the CSV has exactly two columns: 'Timestamp (s)' and 'Sensor X'
|
||||||
|
if df_individual.shape[1] != 2:
|
||||||
|
print(f"Unexpected number of columns in {individual_file_path}. Expected 2, got {df_individual.shape[1]}. Skipping.")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Extract vibration data
|
||||||
|
vibration_data = df_individual.iloc[:, 1].values
|
||||||
|
|
||||||
|
# Perform STFT
|
||||||
|
frequencies, times, Zxx = stft(
|
||||||
|
vibration_data,
|
||||||
|
fs=Fs,
|
||||||
|
window=window,
|
||||||
|
nperseg=window_size,
|
||||||
|
noverlap=window_size - hop_size
|
||||||
|
)
|
||||||
|
|
||||||
|
# Compute magnitude and transpose
|
||||||
|
stft_magnitude = np.abs(Zxx).T # Shape: (513, 513)
|
||||||
|
|
||||||
|
# Select random row indices to verify (e.g., 3 random rows)
|
||||||
|
np.random.seed(42) # For reproducibility
|
||||||
|
sample_row_indices = np.random.choice(stft_magnitude.shape[0], size=3, replace=False)
|
||||||
|
|
||||||
|
# Read the aggregated STFT CSV
|
||||||
|
aggregated_file_name = f'stft_data{sensor_num}_{damage_num}.csv'
|
||||||
|
aggregated_file_path = os.path.join(sensor_dirs[f'sensor{sensor_num}'], aggregated_file_name)
|
||||||
|
|
||||||
|
if not os.path.isfile(aggregated_file_path):
|
||||||
|
print(f"Aggregated file {aggregated_file_path} does not exist. Skipping verification for this test run.")
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
df_aggregated = pd.read_csv(aggregated_file_path)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error reading {aggregated_file_path}: {e}. Skipping verification for this test run.")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Calculate the starting row index in the aggregated CSV
|
||||||
|
# Each test run contributes 513 rows
|
||||||
|
start_row = (test_num - 1) * 513
|
||||||
|
end_row = start_row + 513 # Exclusive
|
||||||
|
|
||||||
|
# Ensure the aggregated CSV has enough rows
|
||||||
|
if df_aggregated.shape[0] < end_row:
|
||||||
|
print(f"Aggregated file {aggregated_file_path} does not have enough rows for Test {test_num}. Skipping.")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Extract the corresponding STFT block from the aggregated CSV
|
||||||
|
df_aggregated_block = df_aggregated.iloc[start_row:end_row].values # Shape: (513, 513)
|
||||||
|
|
||||||
|
# Compare selected rows
|
||||||
|
all_match = True
|
||||||
|
for row_idx in sample_row_indices:
|
||||||
|
individual_row = stft_magnitude[row_idx]
|
||||||
|
aggregated_row = df_aggregated_block[row_idx]
|
||||||
|
|
||||||
|
# Check if the rows are almost equal within a tolerance
|
||||||
|
if np.allclose(individual_row, aggregated_row, atol=1e-6):
|
||||||
|
verification_status = "MATCH"
|
||||||
|
else:
|
||||||
|
verification_status = "MISMATCH"
|
||||||
|
all_match = False
|
||||||
|
|
||||||
|
# Print the comparison details
|
||||||
|
print(f"Comparing Damage {damage_num}, Test {test_num}, Sensor {sensor_num}, Row {row_idx}: {verification_status}")
|
||||||
|
print(f"Individual STFT Row {row_idx}: {individual_row[:5]} ... {individual_row[-5:]}")
|
||||||
|
print(f"Aggregated STFT Row {row_idx + start_row}: {aggregated_row[:5]} ... {aggregated_row[-5:]}\n")
|
||||||
|
|
||||||
|
# If all sampled rows match, print a verification success message
|
||||||
|
if all_match:
|
||||||
|
print(f"STFT of DAMAGE_{damage_num}_TEST{test_num}_{sensor_num}.csv is verified. On `stft_data{sensor_num}_{damage_num}.csv` start at rows {start_row} to {end_row} with 513 rows.\n")
|
||||||
|
else:
|
||||||
|
print(f"STFT of DAMAGE_{damage_num}_TEST{test_num}_{sensor_num}.csv has discrepancies in `stft_data{sensor_num}_{damage_num}.csv` start at rows {start_row} to {end_row} with 513 rows.\n")
|
||||||
|
|
||||||
|
# Define the number of damage cases and test runs
|
||||||
|
num_damage_cases = 6 # Adjust to 30 as per your dataset
|
||||||
|
num_test_runs = 5
|
||||||
|
|
||||||
|
# Iterate through all damage cases, test runs, and sensors
|
||||||
|
for damage_num in range(1, num_damage_cases + 1):
|
||||||
|
for test_num in range(1, num_test_runs + 1):
|
||||||
|
for sensor_num in [1, 2]:
|
||||||
|
verify_stft(damage_num, test_num, sensor_num)
|
||||||
328
data/QUGS/convert.py
Normal file
328
data/QUGS/convert.py
Normal file
@@ -0,0 +1,328 @@
|
|||||||
|
import pandas as pd
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
from colorama import Fore, Style, init
|
||||||
|
from typing import TypedDict, Dict, List
|
||||||
|
from joblib import load
|
||||||
|
from pprint import pprint
|
||||||
|
|
||||||
|
# class DamageFilesIndices(TypedDict):
|
||||||
|
# damage_index: int
|
||||||
|
# files: list[int]
|
||||||
|
OriginalSingleDamageScenarioFilePath = str
|
||||||
|
DamageScenarioGroupIndex = int
|
||||||
|
OriginalSingleDamageScenario = pd.DataFrame
|
||||||
|
SensorIndex = int
|
||||||
|
VectorColumnIndex = List[SensorIndex]
|
||||||
|
VectorColumnIndices = List[VectorColumnIndex]
|
||||||
|
DamageScenarioGroup = List[OriginalSingleDamageScenario]
|
||||||
|
GroupDataset = List[DamageScenarioGroup]
|
||||||
|
|
||||||
|
|
||||||
|
class DamageFilesIndices(TypedDict):
|
||||||
|
damage_index: int
|
||||||
|
files: List[str]
|
||||||
|
|
||||||
|
|
||||||
|
def generate_damage_files_index(**kwargs) -> DamageFilesIndices:
|
||||||
|
prefix: str = kwargs.get("prefix", "zzzAD")
|
||||||
|
extension: str = kwargs.get("extension", ".TXT")
|
||||||
|
num_damage: int = kwargs.get("num_damage")
|
||||||
|
file_index_start: int = kwargs.get("file_index_start")
|
||||||
|
col: int = kwargs.get("col")
|
||||||
|
base_path: str = kwargs.get("base_path")
|
||||||
|
|
||||||
|
damage_scenarios = {}
|
||||||
|
a = file_index_start
|
||||||
|
b = col + 1
|
||||||
|
for i in range(1, num_damage + 1):
|
||||||
|
damage_scenarios[i] = range(a, b)
|
||||||
|
a += col
|
||||||
|
b += col
|
||||||
|
|
||||||
|
# return damage_scenarios
|
||||||
|
|
||||||
|
x = {}
|
||||||
|
for damage, files in damage_scenarios.items():
|
||||||
|
x[damage] = [] # Initialize each key with an empty list
|
||||||
|
for i, file_index in enumerate(files, start=1):
|
||||||
|
if base_path:
|
||||||
|
x[damage].append(
|
||||||
|
os.path.normpath(
|
||||||
|
os.path.join(base_path, f"{prefix}{file_index}{extension}")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
# if not os.path.exists(file_path):
|
||||||
|
# print(Fore.RED + f"File {file_path} does not exist.")
|
||||||
|
# continue
|
||||||
|
else:
|
||||||
|
x[damage].append(f"{prefix}{file_index}{extension}")
|
||||||
|
return x
|
||||||
|
|
||||||
|
# file_path = os.path.join(base_path, f"zzz{prefix}D{file_index}.TXT")
|
||||||
|
# df = pd.read_csv( file_path, sep="\t", skiprows=10) # Read with explicit column names
|
||||||
|
|
||||||
|
|
||||||
|
class DataProcessor:
|
||||||
|
def __init__(self, file_index: DamageFilesIndices, cache_path: str = None):
|
||||||
|
self.file_index = file_index
|
||||||
|
if cache_path:
|
||||||
|
self.data = load(cache_path)
|
||||||
|
else:
|
||||||
|
self.data = self._load_all_data()
|
||||||
|
|
||||||
|
def _extract_column_names(self, file_path: str) -> List[str]:
|
||||||
|
"""
|
||||||
|
Extracts column names from the header of the given file.
|
||||||
|
Assumes the 6th line contains column names.
|
||||||
|
|
||||||
|
:param file_path: Path to the data file.
|
||||||
|
:return: List of column names.
|
||||||
|
"""
|
||||||
|
with open(file_path, "r") as f:
|
||||||
|
header_lines = [next(f) for _ in range(12)]
|
||||||
|
|
||||||
|
# Extract column names from the 6th line
|
||||||
|
channel_line = header_lines[10].strip()
|
||||||
|
tokens = re.findall(r'"([^"]+)"', channel_line)
|
||||||
|
if not channel_line.startswith('"'):
|
||||||
|
first_token = channel_line.split()[0]
|
||||||
|
tokens = [first_token] + tokens
|
||||||
|
|
||||||
|
return tokens # Prepend 'Time' column if applicable
|
||||||
|
|
||||||
|
def _load_dataframe(self, file_path: str) -> OriginalSingleDamageScenario:
|
||||||
|
"""
|
||||||
|
Loads a single data file into a pandas DataFrame.
|
||||||
|
|
||||||
|
:param file_path: Path to the data file.
|
||||||
|
:return: DataFrame containing the numerical data.
|
||||||
|
"""
|
||||||
|
col_names = self._extract_column_names(file_path)
|
||||||
|
df = pd.read_csv(
|
||||||
|
file_path, delim_whitespace=True, skiprows=11, header=None, memory_map=True
|
||||||
|
)
|
||||||
|
df.columns = col_names
|
||||||
|
return df
|
||||||
|
|
||||||
|
def _load_all_data(self) -> GroupDataset:
|
||||||
|
"""
|
||||||
|
Loads all data files based on the grouping dictionary and returns a nested list.
|
||||||
|
|
||||||
|
:return: A nested list of DataFrames where the outer index corresponds to group_idx - 1.
|
||||||
|
"""
|
||||||
|
data = []
|
||||||
|
# Find the maximum group index to determine the list size
|
||||||
|
max_group_idx = max(self.file_index.keys()) if self.file_index else 0
|
||||||
|
|
||||||
|
# Initialize empty lists
|
||||||
|
for _ in range(max_group_idx):
|
||||||
|
data.append([])
|
||||||
|
|
||||||
|
# Fill the list with data
|
||||||
|
for group_idx, file_list in self.file_index.items():
|
||||||
|
# Adjust index to be 0-based
|
||||||
|
list_idx = group_idx - 1
|
||||||
|
data[list_idx] = [self._load_dataframe(file) for file in file_list]
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
def get_group_data(self, group_idx: int) -> List[pd.DataFrame]:
|
||||||
|
"""
|
||||||
|
Returns the list of DataFrames for the given group index.
|
||||||
|
|
||||||
|
:param group_idx: Index of the group.
|
||||||
|
:return: List of DataFrames.
|
||||||
|
"""
|
||||||
|
return self.data.get([group_idx, []])
|
||||||
|
|
||||||
|
def get_column_names(self, group_idx: int, file_idx: int = 0) -> List[str]:
|
||||||
|
"""
|
||||||
|
Returns the column names for the given group and file indices.
|
||||||
|
|
||||||
|
:param group_idx: Index of the group.
|
||||||
|
:param file_idx: Index of the file in the group.
|
||||||
|
:return: List of column names.
|
||||||
|
"""
|
||||||
|
if group_idx in self.data and len(self.data[group_idx]) > file_idx:
|
||||||
|
return self.data[group_idx][file_idx].columns.tolist()
|
||||||
|
return []
|
||||||
|
|
||||||
|
def get_data_info(self):
|
||||||
|
"""
|
||||||
|
Print information about the loaded data structure.
|
||||||
|
Adapted for when self.data is a List instead of a Dictionary.
|
||||||
|
"""
|
||||||
|
if isinstance(self.data, list):
|
||||||
|
# For each sublist in self.data, get the type names of all elements
|
||||||
|
pprint(
|
||||||
|
[
|
||||||
|
(
|
||||||
|
[type(item).__name__ for item in sublist]
|
||||||
|
if isinstance(sublist, list)
|
||||||
|
else type(sublist).__name__
|
||||||
|
)
|
||||||
|
for sublist in self.data
|
||||||
|
]
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
pprint(
|
||||||
|
{
|
||||||
|
key: [type(df).__name__ for df in value]
|
||||||
|
for key, value in self.data.items()
|
||||||
|
}
|
||||||
|
if isinstance(self.data, dict)
|
||||||
|
else type(self.data).__name__
|
||||||
|
)
|
||||||
|
|
||||||
|
def _create_vector_column_index(self) -> VectorColumnIndices:
|
||||||
|
vector_col_idx: VectorColumnIndices = []
|
||||||
|
y = 0
|
||||||
|
for data_group in self.data: # len(data_group[i]) = 5
|
||||||
|
for j in data_group: # len(j[i]) =
|
||||||
|
c: VectorColumnIndex = [] # column vector c_{j}
|
||||||
|
x = 0
|
||||||
|
for _ in range(6): # TODO: range(6) should be dynamic and parameterized
|
||||||
|
c.append(x + y)
|
||||||
|
x += 5
|
||||||
|
vector_col_idx.append(c)
|
||||||
|
y += 1
|
||||||
|
return vector_col_idx
|
||||||
|
|
||||||
|
def create_vector_column(self, overwrite=True) -> List[List[List[pd.DataFrame]]]:
|
||||||
|
"""
|
||||||
|
Create a vector column from the loaded data.
|
||||||
|
|
||||||
|
:param overwrite: Overwrite the original data with vector column-based data.
|
||||||
|
"""
|
||||||
|
idx = self._create_vector_column_index()
|
||||||
|
# if overwrite:
|
||||||
|
for i in range(len(self.data)):
|
||||||
|
for j in range(len(self.data[i])):
|
||||||
|
# Get the appropriate indices for slicing from idx
|
||||||
|
indices = idx[j]
|
||||||
|
|
||||||
|
# Get the current DataFrame
|
||||||
|
df = self.data[i][j]
|
||||||
|
|
||||||
|
# Keep the 'Time' column and select only specified 'Real' columns
|
||||||
|
# First, we add 1 to all indices to account for 'Time' being at position 0
|
||||||
|
real_indices = [index + 1 for index in indices]
|
||||||
|
|
||||||
|
# Create list with Time column index (0) and the adjusted Real indices
|
||||||
|
all_indices = [0] + real_indices
|
||||||
|
|
||||||
|
# Apply the slicing
|
||||||
|
self.data[i][j] = df.iloc[:, all_indices]
|
||||||
|
# TODO: if !overwrite:
|
||||||
|
|
||||||
|
def create_limited_sensor_vector_column(self, overwrite=True):
|
||||||
|
"""
|
||||||
|
Create a vector column from the loaded data.
|
||||||
|
|
||||||
|
:param overwrite: Overwrite the original data with vector column-based data.
|
||||||
|
"""
|
||||||
|
idx = self._create_vector_column_index()
|
||||||
|
# if overwrite:
|
||||||
|
for i in range(len(self.data)):
|
||||||
|
for j in range(len(self.data[i])):
|
||||||
|
# Get the appropriate indices for slicing from idx
|
||||||
|
indices = idx[j]
|
||||||
|
|
||||||
|
# Get the current DataFrame
|
||||||
|
df = self.data[i][j]
|
||||||
|
|
||||||
|
# Keep the 'Time' column and select only specified 'Real' columns
|
||||||
|
# First, we add 1 to all indices to account for 'Time' being at position 0
|
||||||
|
real_indices = [index + 1 for index in indices]
|
||||||
|
|
||||||
|
# Create list with Time column index (0) and the adjusted Real indices
|
||||||
|
all_indices = [0] + [real_indices[0]] + [real_indices[-1]]
|
||||||
|
|
||||||
|
# Apply the slicing
|
||||||
|
self.data[i][j] = df.iloc[:, all_indices]
|
||||||
|
# TODO: if !overwrite:
|
||||||
|
|
||||||
|
|
||||||
|
def create_damage_files(base_path, output_base, prefix):
|
||||||
|
# Initialize colorama
|
||||||
|
init(autoreset=True)
|
||||||
|
|
||||||
|
# Generate column labels based on expected duplication in input files
|
||||||
|
columns = ["Real"] + [
|
||||||
|
f"Real.{i}" for i in range(1, 30)
|
||||||
|
] # Explicitly setting column names
|
||||||
|
|
||||||
|
sensor_end_map = {
|
||||||
|
1: "Real.25",
|
||||||
|
2: "Real.26",
|
||||||
|
3: "Real.27",
|
||||||
|
4: "Real.28",
|
||||||
|
5: "Real.29",
|
||||||
|
}
|
||||||
|
|
||||||
|
# Define the damage scenarios and the corresponding original file indices
|
||||||
|
damage_scenarios = {
|
||||||
|
1: range(1, 6), # Damage 1 files from zzzAD1.csv to zzzAD5.csv
|
||||||
|
2: range(6, 11), # Damage 2 files from zzzAD6.csv to zzzAD10.csv
|
||||||
|
3: range(11, 16), # Damage 3 files from zzzAD11.csv to zzzAD15.csvs
|
||||||
|
4: range(16, 21), # Damage 4 files from zzzAD16.csv to zzzAD20.csv
|
||||||
|
5: range(21, 26), # Damage 5 files from zzzAD21.csv to zzzAD25.csv
|
||||||
|
6: range(26, 31), # Damage 6 files from zzzAD26.csv to zzzAD30.csv
|
||||||
|
}
|
||||||
|
damage_pad = len(str(len(damage_scenarios)))
|
||||||
|
test_pad = len(str(30))
|
||||||
|
|
||||||
|
for damage, files in damage_scenarios.items():
|
||||||
|
for i, file_index in enumerate(files, start=1):
|
||||||
|
# Load original data file
|
||||||
|
file_path = os.path.join(base_path, f"zzz{prefix}D{file_index}.TXT")
|
||||||
|
df = pd.read_csv(
|
||||||
|
file_path, sep="\t", skiprows=10
|
||||||
|
) # Read with explicit column names
|
||||||
|
|
||||||
|
top_sensor = columns[i - 1]
|
||||||
|
print(top_sensor, type(top_sensor))
|
||||||
|
output_file_1 = os.path.join(
|
||||||
|
output_base, f"DAMAGE_{damage}", f"DAMAGE{damage}_TEST{i}_01.csv"
|
||||||
|
)
|
||||||
|
print(f"Creating {output_file_1} from taking zzz{prefix}D{file_index}.TXT")
|
||||||
|
print("Taking datetime column on index 0...")
|
||||||
|
print(f"Taking `{top_sensor}`...")
|
||||||
|
os.makedirs(os.path.dirname(output_file_1), exist_ok=True)
|
||||||
|
df[["Time", top_sensor]].to_csv(output_file_1, index=False)
|
||||||
|
print(Fore.GREEN + "Done")
|
||||||
|
|
||||||
|
bottom_sensor = sensor_end_map[i]
|
||||||
|
output_file_2 = os.path.join(
|
||||||
|
output_base, f"DAMAGE_{damage}", f"DAMAGE{damage}_TEST{i}_02.csv"
|
||||||
|
)
|
||||||
|
print(f"Creating {output_file_2} from taking zzz{prefix}D{file_index}.TXT")
|
||||||
|
print("Taking datetime column on index 0...")
|
||||||
|
print(f"Taking `{bottom_sensor}`...")
|
||||||
|
os.makedirs(os.path.dirname(output_file_2), exist_ok=True)
|
||||||
|
df[["Time", bottom_sensor]].to_csv(output_file_2, index=False)
|
||||||
|
print(Fore.GREEN + "Done")
|
||||||
|
print("---")
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
if len(sys.argv) < 2:
|
||||||
|
print("Usage: python convert.py <path_to_csv_files>")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
base_path = sys.argv[1]
|
||||||
|
output_base = sys.argv[2]
|
||||||
|
prefix = sys.argv[3] # Define output directory
|
||||||
|
|
||||||
|
# Create output folders if they don't exist
|
||||||
|
# for i in range(1, 7):
|
||||||
|
# os.makedirs(os.path.join(output_base, f'DAMAGE_{i}'), exist_ok=True)
|
||||||
|
|
||||||
|
create_damage_files(base_path, output_base, prefix)
|
||||||
|
print(Fore.YELLOW + Style.BRIGHT + "All files have been created successfully.")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
8
data/QUGS/test.py
Normal file
8
data/QUGS/test.py
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
from convert import *
|
||||||
|
from joblib import dump, load
|
||||||
|
|
||||||
|
# a = generate_damage_files_index(
|
||||||
|
# num_damage=6, file_index_start=1, col=5, base_path="D:/thesis/data/dataset_A"
|
||||||
|
# )
|
||||||
|
# dump(DataProcessor(file_index=a), "D:/cache.joblib")
|
||||||
|
a = load("D:/cache.joblib")
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
# Processed Data Directory
|
# Raw Data Directory
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
This `data/processed` directory contains structured data that has been processed and formatted for analysis. Each subdirectory within `processed` represents a different level of simulated damage, and each contains multiple test files from experiments conducted under that specific damage scenario.
|
This `data/raw` directory contains structured data that has been processed and formatted for analysis. Each subdirectory within `raw` represents a different level of simulated damage, and each contains multiple test files from experiments conducted under that specific damage scenario.
|
||||||
|
|
||||||
## Directory Structure
|
## Directory Structure
|
||||||
|
|
||||||
@@ -12,12 +12,12 @@ The directory is organized as follows:
|
|||||||
data
|
data
|
||||||
└── processed
|
└── processed
|
||||||
├── DAMAGE_1
|
├── DAMAGE_1
|
||||||
│ ├── D1_TEST1.csv
|
│ ├── D1_TEST1.csv
|
||||||
│ ├── D1_TEST2.csv
|
│ ├── D1_TEST2.csv
|
||||||
│ ...
|
│ ...
|
||||||
│ └── D1_TEST10.csv
|
│ └── D1_TEST10.csv
|
||||||
├── DAMAGE_2
|
├── DAMAGE_2
|
||||||
│ ├── D2_TEST1.csv
|
│ ├── D2_TEST1.csv
|
||||||
│ ...
|
│ ...
|
||||||
├── DAMAGE_3
|
├── DAMAGE_3
|
||||||
│ ...
|
│ ...
|
||||||
66
docs/CONTRIBUTING.md
Normal file
66
docs/CONTRIBUTING.md
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
This document outlines the process for developing and contributing to my own thesis project. By following these guidelines, this will ensure consistent quality and maintain a clear development history.
|
||||||
|
|
||||||
|
## Development Workflow
|
||||||
|
|
||||||
|
### 1. Issue Creation
|
||||||
|
Before working on any new feature, experiment, or bug fix:
|
||||||
|
- Create a GitHub issue using the appropriate template
|
||||||
|
- Assign it to myself
|
||||||
|
- Add relevant labels
|
||||||
|
- Link it to the project board if applicable
|
||||||
|
|
||||||
|
### 2. Branching Strategy
|
||||||
|
Use the following branch naming convention:
|
||||||
|
- `feature/<issue-number>-short-description`
|
||||||
|
- `bugfix/<issue-number>-short-description`
|
||||||
|
- `experiment/<issue-number>-short-description`
|
||||||
|
- `doc/<issue-number>-short-description`
|
||||||
|
|
||||||
|
Always branch from `main` for new features/experiments.
|
||||||
|
|
||||||
|
### 3. Development Process
|
||||||
|
- Make regular, atomic commits following the commit message template
|
||||||
|
- Include the issue number in commit messages (e.g., "#42")
|
||||||
|
- Push changes at the end of each work session
|
||||||
|
|
||||||
|
### 4. Code Quality
|
||||||
|
- Follow PEP 8 guidelines for Python code
|
||||||
|
- Document functions with docstrings
|
||||||
|
- Maintain test coverage for custom functions
|
||||||
|
- Keep notebooks clean and well-documented
|
||||||
|
|
||||||
|
### 5. Pull Requests
|
||||||
|
Even working alone, use PRs for significant changes:
|
||||||
|
- Create a PR from your feature branch to `main`
|
||||||
|
- Reference the issue(s) it resolves
|
||||||
|
- Include a summary of changes
|
||||||
|
- Self-review the PR before merging
|
||||||
|
|
||||||
|
### 6. Versioning
|
||||||
|
Follow semantic versioning:
|
||||||
|
- Major version: Significant thesis milestones or structural changes
|
||||||
|
- Minor version: New experiments, features, or chapters
|
||||||
|
- Patch version: Bug fixes and minor improvements
|
||||||
|
|
||||||
|
### 7. Documentation
|
||||||
|
Update documentation with each significant change:
|
||||||
|
- Keep README current
|
||||||
|
- Update function documentation
|
||||||
|
- Maintain clear experiment descriptions in notebooks
|
||||||
|
- Record significant decisions and findings
|
||||||
|
|
||||||
|
## LaTeX Guidelines
|
||||||
|
- Use consistent citation style
|
||||||
|
- Break long sections into multiple files
|
||||||
|
- Use meaningful label names for cross-references
|
||||||
|
- Consider using version-control friendly LaTeX practices (one sentence per line)
|
||||||
|
|
||||||
|
## Experiment Tracking
|
||||||
|
For each experiment:
|
||||||
|
- Create an issue documenting the experiment design
|
||||||
|
- Reference related papers and previous experiments
|
||||||
|
- Document parameters and results in the notebook
|
||||||
|
- Summarize findings in the issue before closing
|
||||||
|
|
||||||
|
## Commit Categories
|
||||||
|
Use the categories defined in the commit template to clearly classify changes.
|
||||||
@@ -13,29 +13,38 @@ processed_path = os.path.join(base_path, "processed")
|
|||||||
os.makedirs(raw_path, exist_ok=True)
|
os.makedirs(raw_path, exist_ok=True)
|
||||||
os.makedirs(processed_path, exist_ok=True)
|
os.makedirs(processed_path, exist_ok=True)
|
||||||
|
|
||||||
for damage in range(1, 6): # 5 Damage levels
|
# Define the number of zeros to pad
|
||||||
damage_folder = f"DAMAGE_{damage}"
|
num_damages = 5
|
||||||
damage_path = os.path.join(processed_path, damage_folder)
|
num_tests = 10
|
||||||
|
num_sensors = 2
|
||||||
|
damage_pad = len(str(num_damages))
|
||||||
|
test_pad = len(str(num_tests))
|
||||||
|
sensor_pad = len(str(num_sensors))
|
||||||
|
|
||||||
|
for damage in range(1, num_damages + 1): # 5 Damage levels starts from 1
|
||||||
|
damage_folder = f"DAMAGE_{damage:0{damage_pad}}"
|
||||||
|
damage_path = os.path.join(raw_path, damage_folder)
|
||||||
os.makedirs(damage_path, exist_ok=True)
|
os.makedirs(damage_path, exist_ok=True)
|
||||||
|
|
||||||
for test in range(1, 11): # 10 Tests per damage level
|
for test in range(1, 11): # 10 Tests per damage level
|
||||||
# Filename for the CSV
|
for sensor in range(1, 3): # 2 Sensors per test
|
||||||
csv_filename = f"D{damage}_TEST{test}.csv"
|
# Filename for the CSV
|
||||||
csv_path = os.path.join(damage_path, csv_filename)
|
csv_filename = f"D{damage:0{damage_pad}}_TEST{test:0{test_pad}}_{sensor:0{sensor_pad}}.csv"
|
||||||
|
csv_path = os.path.join(damage_path, csv_filename)
|
||||||
|
|
||||||
|
# Generate dummy data
|
||||||
|
num_rows = 10
|
||||||
|
start_time = datetime.now()
|
||||||
|
timestamps = [start_time + timedelta(seconds=i*0.0078125) for i in range(num_rows)]
|
||||||
|
values = np.random.randn(num_rows) # Random float values
|
||||||
|
|
||||||
# Generate dummy data
|
# Create DataFrame
|
||||||
num_rows = 10
|
df = pd.DataFrame({
|
||||||
start_time = datetime.now()
|
"Time": timestamps,
|
||||||
timestamps = [start_time + timedelta(seconds=i*0.0078125) for i in range(num_rows)]
|
"Value": values
|
||||||
values = np.random.randn(num_rows) # Random float values
|
})
|
||||||
|
|
||||||
# Create DataFrame
|
# Save the CSV file with a custom header
|
||||||
df = pd.DataFrame({
|
with open(csv_path, 'w') as file:
|
||||||
"Time": timestamps,
|
file.write('sep=,\n') # Writing the separator hint
|
||||||
"Value": values
|
df.to_csv(file, index=False)
|
||||||
})
|
|
||||||
|
|
||||||
# Save the CSV file with a custom header
|
|
||||||
with open(csv_path, 'w') as file:
|
|
||||||
file.write('sep=,\n') # Writing the separator hint
|
|
||||||
df.to_csv(file, index=False)
|
|
||||||
|
|||||||
41
latex/appendix/important/abdeljaber2017.tex
Normal file
41
latex/appendix/important/abdeljaber2017.tex
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
2 %Nomor
|
||||||
|
|
||||||
|
%for mult rows
|
||||||
|
|
||||||
|
& %Judul Jurnal
|
||||||
|
Real-time vibration-based structural damage detection using one-dimensional convolutional neural networks \href{https://doi.org/10.1016/j.jsv.2016.10.043}{10.1016/j.jsv.
|
||||||
|
2016.10.043}
|
||||||
|
|
||||||
|
%for mult rows
|
||||||
|
|
||||||
|
% & %Author
|
||||||
|
% % Satish B Satpal; Yogesh Khandare; Anirban Guha; Sauvik Banerjee
|
||||||
|
|
||||||
|
% %for mult rows
|
||||||
|
|
||||||
|
% & %Nama Jurnal
|
||||||
|
% International Journal of Advanced Structural Engineering (IJASE)
|
||||||
|
|
||||||
|
% %for mult rows
|
||||||
|
|
||||||
|
% & %Sumber
|
||||||
|
% \href{http://dx.doi.org/10.1186/2008-6695-5-2}{ResearchGate}
|
||||||
|
|
||||||
|
% %for mult rows
|
||||||
|
|
||||||
|
% & %Tahun
|
||||||
|
% 2020
|
||||||
|
|
||||||
|
% %for mult rows
|
||||||
|
|
||||||
|
& %Tujuan penelitian
|
||||||
|
Mengidentifikasi lokasi kerusakan struktur secara \textit{real-time} dengan memproses sinyal getaran mentah yang diambil dari jaringan-jaringan akselerometer pada setiap titik tanpa proses tambahan atau ekstraksi fitur.
|
||||||
|
|
||||||
|
& %Kesimpulan
|
||||||
|
% Studi ini menilai kemampuan mesin vektor pendukung untuk memprediksi intensitas kerusakan dan lokasi pada balok kantilever. Meskipun berhasil memprediksi kerusakan dengan sedikit kesalahan, tingkat kebisingan dan lokasi kerusakan memengaruhi keakuratan. Tingkat kebisingan yang tinggi mempengaruhi kinerja secara signifikan, terutama pada intensitas kerusakan yang lebih rendah.
|
||||||
|
& % Gap Research
|
||||||
|
\begin{enumerate}
|
||||||
|
\item Riset ini hanya dilakukan dengan \textit{full-grid array} akselerometer yang diletakkan pada setiap \textit{node} kerusakan, sehingga memerlukan banyak perangkat akselerometer.
|
||||||
|
|
||||||
|
\item Tidak ada komparasi performa efisiensi dan akurasi dengan algoritma pembelajaran mesin lain yang lebih populer sebelumnya.
|
||||||
|
\end{enumerate}
|
||||||
68
latex/appendix/important/van2020.tex
Normal file
68
latex/appendix/important/van2020.tex
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
1
|
||||||
|
|
||||||
|
%for mult rows
|
||||||
|
|
||||||
|
&
|
||||||
|
Statistical Feature Extraction in Machine Fault Detection using Vibration Signal (\href{https://doi.org/10.1109/ICTC49870.2020.9289285}{10.1109/ICTC49870.
|
||||||
|
2020.9289285})
|
||||||
|
%for mult rows
|
||||||
|
|
||||||
|
% &
|
||||||
|
% Donghui Xu; Xiang Xu; Michael C. Forde; Antonio Caballero
|
||||||
|
|
||||||
|
%for mult rows
|
||||||
|
|
||||||
|
% &
|
||||||
|
% Construction and Building Materials
|
||||||
|
|
||||||
|
% %for mult rows
|
||||||
|
|
||||||
|
% &
|
||||||
|
% \href{https://doi.org/10.1016/j.conbuildmat.2023.132596}{ScienceDirect}
|
||||||
|
|
||||||
|
% %for mult rows
|
||||||
|
|
||||||
|
% &
|
||||||
|
% 2023
|
||||||
|
|
||||||
|
% %for mult rows
|
||||||
|
|
||||||
|
&
|
||||||
|
\begin{enumerate}[series=enum]
|
||||||
|
\item Menginvestigasi cara mengklasifikasi kondisi \textit{gearbox} normal dan rusak menggunakan sinyal getaran berbasis pada kombinasi antara analisis statistik dan FFT dengan algoritma pembelajaran mesin (ANN, Logistic Regression, dan SVM)
|
||||||
|
|
||||||
|
\item Mengurangi waktu latih dan kompleksitas kalkulasi dengan analisis statistik sebagai input data meliputi sembilan fitur: mean, median, min, max, kurtosis, \textit{skewness}, \textit{standard deviation}, and \textit{range}.
|
||||||
|
\end{enumerate}
|
||||||
|
|
||||||
|
&
|
||||||
|
\begin{enumerate}[series=enum2]
|
||||||
|
\item Nilai \textit{maximum} dan kurtosis adalah fitur yang paling signifikan untuk mengklasifikasi kelas label pembelajaran mesin.
|
||||||
|
|
||||||
|
\item ANN meraih akurasi 100\% pada input FFT penuh dan analisis statistik, sedangkan Regresi Logistik (LR) dan SVM meraih akurasi 100\% dengan input FFT penuh namun hanya mendapat akurasi 91\% dengan input analisis statistik
|
||||||
|
\end{enumerate}
|
||||||
|
|
||||||
|
&
|
||||||
|
\begin{enumerate}
|
||||||
|
\item Lorem
|
||||||
|
\item Ipsum
|
||||||
|
\end{enumerate}
|
||||||
|
|
||||||
|
%-------------page break----------------
|
||||||
|
% \\
|
||||||
|
% &
|
||||||
|
% &
|
||||||
|
% &
|
||||||
|
% &
|
||||||
|
% &
|
||||||
|
% &
|
||||||
|
% &
|
||||||
|
% \begin{enumerate}[resume=enum]
|
||||||
|
% \item Menyajikan berbagai perkembangan penelitian, mendiskusikan dan membandingkannya kelebihan dan kekurangannya
|
||||||
|
% \item Meringkas kesesuaian berbagai metode pembelajaran mesin untuk masalah SHM yang berbeda
|
||||||
|
% \item Terakhir, tren masa depan
|
||||||
|
% \end{enumerate}
|
||||||
|
% &
|
||||||
|
% \begin{enumerate}[resume=enum2]
|
||||||
|
% \item SVM dan hutan acak kurang mendapat perhatian dibandingkan dengan jaringan saraf. Ini digunakan untuk klasifikasi kerusakan. Namun, pemrosesan awal data jauh lebih rumit.
|
||||||
|
|
||||||
|
% \end{enumerate}
|
||||||
509
latex/appendix/summary_related_paper.tex
Normal file
509
latex/appendix/summary_related_paper.tex
Normal file
@@ -0,0 +1,509 @@
|
|||||||
|
\documentclass[12pt,a4paper]{report}
|
||||||
|
\usepackage{hyperref}
|
||||||
|
\usepackage[top=1cm,right=3cm,bottom=1cm,left=3cm]{geometry}
|
||||||
|
\usepackage{multirow}
|
||||||
|
\usepackage{array}
|
||||||
|
% \usepackage{makecell}
|
||||||
|
\usepackage{pdflscape}
|
||||||
|
\usepackage{longtable,booktabs}
|
||||||
|
\usepackage{colortbl,xcolor}
|
||||||
|
\usepackage{enumitem}
|
||||||
|
\usepackage{pdfpages}
|
||||||
|
\usepackage{caption}
|
||||||
|
\usepackage[bahasa]{babel}
|
||||||
|
\usepackage{xpatch,csquotes}
|
||||||
|
\usepackage[backend=biber]{biblatex}
|
||||||
|
\addbibresource{export.bib}
|
||||||
|
\DeclareSourcemap{
|
||||||
|
\maps[datatype = bibtex]{
|
||||||
|
\map{
|
||||||
|
\step[fieldsource = abstract,
|
||||||
|
match = \regexp{([^\\])\%},
|
||||||
|
replace = \regexp{\$1\\\%}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
% \usepackage{tablefootnote}
|
||||||
|
% \usepackage{showframe}
|
||||||
|
\definecolor{Gray}{gray}{0.95}
|
||||||
|
\newcolumntype{a}{>{\columncolor{Gray}}p}
|
||||||
|
\renewcommand{\thefootnote}{\textit{\alph{footnote}}}
|
||||||
|
% \newcolumntype{b}{>{\raggedright\arraybackslash}p}
|
||||||
|
|
||||||
|
\title{Tugas 2 \\ Metode Penelitian}
|
||||||
|
\author{Rifqi Damar Panuluh \\ 20210110224}
|
||||||
|
|
||||||
|
\begin{document}
|
||||||
|
\maketitle
|
||||||
|
\begin{landscape}
|
||||||
|
% Table generated by Excel2LaTeX from sheet 'Sheet1'
|
||||||
|
% \begin{table}[h]
|
||||||
|
\centering
|
||||||
|
\begin{longtable}{
|
||||||
|
>{\raggedleft\arraybackslash}p{0.02\linewidth} %1
|
||||||
|
>{\raggedright\arraybackslash}a{0.1\linewidth} %2
|
||||||
|
% >{\raggedright\arraybackslash}p{0.1\linewidth} %3
|
||||||
|
% >{\raggedright\arraybackslash}a{0.075\linewidth} %4
|
||||||
|
% p{0.065\linewidth} %5
|
||||||
|
% >{\raggedleft\arraybackslash}p{0.05\linewidth} %6
|
||||||
|
>{\raggedright\arraybackslash}p{0.25\linewidth} %7
|
||||||
|
>{\raggedright\arraybackslash}a{0.25\linewidth} %8
|
||||||
|
>{\raggedright\arraybackslash}p{0.25\linewidth} %9
|
||||||
|
}
|
||||||
|
|
||||||
|
\caption{Tinjauan pustaka, topik: pemanfaatan data getaran untuk monitor kesehatan struktur jembatan}
|
||||||
|
\label{tab:my_label}
|
||||||
|
\\
|
||||||
|
\toprule
|
||||||
|
\toprule
|
||||||
|
\rowcolor{white}
|
||||||
|
No. %1
|
||||||
|
&
|
||||||
|
Judul %2
|
||||||
|
% &
|
||||||
|
% Nama Penulis %3
|
||||||
|
% &
|
||||||
|
% Nama Jurnal %4
|
||||||
|
% &
|
||||||
|
% Sumber %5
|
||||||
|
% &
|
||||||
|
% Tahun %6
|
||||||
|
&
|
||||||
|
Tujuan Penelitian %7
|
||||||
|
&
|
||||||
|
Kesimpulan %8
|
||||||
|
&
|
||||||
|
Gap Research %9
|
||||||
|
|
||||||
|
\\\midrule
|
||||||
|
\endfirsthead
|
||||||
|
\toprule
|
||||||
|
\rowcolor{white}
|
||||||
|
No. %1
|
||||||
|
&
|
||||||
|
Judul %2
|
||||||
|
% &
|
||||||
|
% Nama Penulis %3
|
||||||
|
% &
|
||||||
|
% Nama Jurnal %4
|
||||||
|
% &
|
||||||
|
% Sumber %5
|
||||||
|
% &
|
||||||
|
% Tahun %6
|
||||||
|
&
|
||||||
|
Tujuan Penelitian %7
|
||||||
|
&
|
||||||
|
Kesimpulan %8
|
||||||
|
|
||||||
|
\\\midrule
|
||||||
|
\endhead
|
||||||
|
\midrule
|
||||||
|
\multicolumn{4}{r}{\textit{berlanjut di halaman berikutnya}}
|
||||||
|
\endfoot
|
||||||
|
\bottomrule
|
||||||
|
\bottomrule
|
||||||
|
\endlastfoot
|
||||||
|
|
||||||
|
%-----1
|
||||||
|
\input{important/van2020}
|
||||||
|
\\
|
||||||
|
%-----2
|
||||||
|
\input{important/abdeljaber2017}
|
||||||
|
\\
|
||||||
|
%------3
|
||||||
|
\\
|
||||||
|
3
|
||||||
|
|
||||||
|
& %Judul Jurnal
|
||||||
|
Real-time nondestructive structural health monitoring using support vector machines and wavelets (Ahmet Bulut; Ambuj K. Singh; Peter Shin; Tony Fountain; Hector Jasso; Linjun Yan; Ahmed Elgamal)
|
||||||
|
|
||||||
|
%for mult rows
|
||||||
|
|
||||||
|
% & %Author
|
||||||
|
% Ahmet Bulut; Ambuj K. Singh; Peter Shin; Tony Fountain; Hector Jasso; Linjun Yan; Ahmed Elgamal
|
||||||
|
|
||||||
|
%for mult rows
|
||||||
|
|
||||||
|
% & %Nama Jurnal
|
||||||
|
% Case Studies in Construction Materials 13 (2020) e00406
|
||||||
|
|
||||||
|
% %for mult rows
|
||||||
|
|
||||||
|
% & %Sumber
|
||||||
|
% SPIE
|
||||||
|
|
||||||
|
% %for mult rows
|
||||||
|
|
||||||
|
% & %Tahun
|
||||||
|
% 2005
|
||||||
|
|
||||||
|
%for mult rows
|
||||||
|
|
||||||
|
& %Tujuan penelitian
|
||||||
|
Eksplorasi efektivitas SVM dalam deteksi kerusakan; Validasi model SVM dengan data nyata jembatan
|
||||||
|
|
||||||
|
& %Kesimpulan
|
||||||
|
\begin{enumerate} [series=enum]
|
||||||
|
\item SVM menunjukkan akurasi tinggi dalam mengidentifikasi lokasi kerusakan
|
||||||
|
\item Rekomendasi untuk penyetelan parameter SVM
|
||||||
|
\end{enumerate}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
%-----------4
|
||||||
|
\\
|
||||||
|
4
|
||||||
|
|
||||||
|
& %Judul Jurnal
|
||||||
|
A novel approach of Structural Health Monitoring by the application of FFT and wavelet transform using an index of frequency dispersion (Fragkiskos P. Pentaris; John Stonham; John P. Makris)
|
||||||
|
|
||||||
|
%for mult rows
|
||||||
|
|
||||||
|
% & %Author
|
||||||
|
% Fragkiskos P. Pentaris; John Stonham; John P. Makris
|
||||||
|
|
||||||
|
%for mult rows
|
||||||
|
|
||||||
|
% & %Nama Jurnal
|
||||||
|
% International Journal of Geology
|
||||||
|
|
||||||
|
% %for mult rows
|
||||||
|
|
||||||
|
% & %Sumber
|
||||||
|
% Research Gate
|
||||||
|
|
||||||
|
% %for mult rows
|
||||||
|
|
||||||
|
% & %Tahun
|
||||||
|
% 2013
|
||||||
|
|
||||||
|
%for mult rows
|
||||||
|
|
||||||
|
& %Tujuan penelitian
|
||||||
|
\begin{enumerate}
|
||||||
|
\item Memeriksa peran FFT dalam pemrosesan awal data getaran
|
||||||
|
\item Menilai dampak FFT terhadap keakuratan deteksi kerusakan
|
||||||
|
\end{enumerate}
|
||||||
|
|
||||||
|
& %Kesimpulan
|
||||||
|
\begin{enumerate} [series=enum]
|
||||||
|
\item FFT meningkatkan rasio \textit{signal-to-noise} dan meningkatkan deteksi kerusakan.
|
||||||
|
\item Menyarankan integrasi dengan algoritme lain untuk meningkatkan akurasi.
|
||||||
|
\end{enumerate}
|
||||||
|
|
||||||
|
\\ %-------------page break----------------
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
%-----------4
|
||||||
|
\\
|
||||||
|
5
|
||||||
|
|
||||||
|
& %Judul Jurnal
|
||||||
|
Review of Vibration-Based Structural Health Monitoring Using Deep Learning (Gyungmin Toh; Junhong Park)
|
||||||
|
|
||||||
|
%for mult rows
|
||||||
|
|
||||||
|
% & %Author
|
||||||
|
% Gyungmin Toh;
|
||||||
|
% Junhong Park
|
||||||
|
|
||||||
|
% %for mult rows
|
||||||
|
|
||||||
|
% & %Nama Jurnal
|
||||||
|
% Apllied Sciences
|
||||||
|
|
||||||
|
% %for mult rows
|
||||||
|
|
||||||
|
% & %Sumber
|
||||||
|
% MDPI
|
||||||
|
|
||||||
|
% %for mult rows
|
||||||
|
|
||||||
|
% & %Tahun
|
||||||
|
% 2020
|
||||||
|
|
||||||
|
%for mult rows
|
||||||
|
|
||||||
|
& %Tujuan penelitian
|
||||||
|
\begin{enumerate}
|
||||||
|
\item ringkasan studi penerapan algoritma pembelajaran mesin untuk kesalahan pemantauan (\textit{monitoring}) menggunakan faktor getaran untuk mengkategorikan penelitian.
|
||||||
|
\item Menyediakan interpretasi singkat tentang jaringan saraf dalam untuk pengaplikasian lebih lanjut dalam analisis getaran struktural.
|
||||||
|
\end{enumerate}
|
||||||
|
|
||||||
|
& %Kesimpulan
|
||||||
|
\begin{enumerate} [series=enum]
|
||||||
|
\item Deep learning has the advantage of being able to perform health monitoring on complex structures with high accuracy.
|
||||||
|
\end{enumerate}
|
||||||
|
%-------------page break----------------
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
%-----------4
|
||||||
|
\\
|
||||||
|
6
|
||||||
|
|
||||||
|
& %Judul Jurnal
|
||||||
|
A deep learning approach to condition monitoring of cantilever beams via time-frequency extended signatures (Habil. Darian M. Onchis)
|
||||||
|
|
||||||
|
%for mult rows
|
||||||
|
|
||||||
|
% & %Author
|
||||||
|
% Habil. Darian M. Onchis
|
||||||
|
|
||||||
|
% %for mult rows
|
||||||
|
|
||||||
|
% & %Nama Jurnal
|
||||||
|
% Computers in Industry
|
||||||
|
|
||||||
|
% %for mult rows
|
||||||
|
|
||||||
|
% & %Sumber
|
||||||
|
% Science Direct
|
||||||
|
|
||||||
|
% %for mult rows
|
||||||
|
|
||||||
|
% & %Tahun
|
||||||
|
% 2019
|
||||||
|
|
||||||
|
%for mult rows
|
||||||
|
|
||||||
|
& %Tujuan penelitian
|
||||||
|
\begin{enumerate}
|
||||||
|
\item ringkasan studi penerapan algoritma pembelajaran mesin untuk kesalahan pemantauan (\textit{monitoring}) menggunakan faktor getaran untuk mengkategorikan penelitian.
|
||||||
|
\item Menyediakan interpretasi singkat tentang jaringan saraf dalam untuk pengaplikasian lebih lanjut dalam analisis getaran struktural.
|
||||||
|
\end{enumerate}
|
||||||
|
|
||||||
|
& %Kesimpulan
|
||||||
|
\begin{enumerate} [series=enum]
|
||||||
|
\item Deep learning has the advantage of being able to perform health monitoring on complex structures with high accuracy.
|
||||||
|
\end{enumerate}
|
||||||
|
|
||||||
|
\\ %-------------page break----------------
|
||||||
|
|
||||||
|
|
||||||
|
% %------------5
|
||||||
|
% 5
|
||||||
|
|
||||||
|
% & %Judul Jurnal
|
||||||
|
% Advances and development trends in eco-friendly pavements
|
||||||
|
|
||||||
|
% %for mult rows
|
||||||
|
|
||||||
|
% & %Author
|
||||||
|
% Aimin Sha, Zhuangzhuang Liu, Wei Jiang, Lin Qi, Liqun Hu, Wenxiu Jiao ,Diego Maria Barbieri
|
||||||
|
|
||||||
|
% %for mult rows
|
||||||
|
|
||||||
|
% & %Nama Jurnal
|
||||||
|
% Journal of Road Engineering 1 (2021)
|
||||||
|
|
||||||
|
% %for mult rows
|
||||||
|
|
||||||
|
% & %Sumber
|
||||||
|
% ScienceDirect
|
||||||
|
|
||||||
|
% %for mult rows
|
||||||
|
|
||||||
|
% & %Tahun
|
||||||
|
% 2021
|
||||||
|
|
||||||
|
% %for mult rows
|
||||||
|
|
||||||
|
% & %Tujuan penelitian
|
||||||
|
% Mengembangkan solusi teknis untuk mengatasi tantangan yang terkait dengan penciptaan infrastruktur hijau dan berkelanjutan, misalnya, pengurangan dampak lingkungan, peningkatan keselamatan lalu lintas, dan efisiensi transportasi, dll.\cite{Sha2021}
|
||||||
|
% &
|
||||||
|
% \begin{enumerate} [series=enum]
|
||||||
|
% \item Temuan penelitian terbaru terkait jalan ramah lingkungan
|
||||||
|
% trotoar diringkas dan dibahas sesuai dengan enam kunci yang berbeda
|
||||||
|
% karakteristik: permeabel, pengurangan kebisingan, luminescence diri, knalpot
|
||||||
|
% dekomposisi, penyerapan panas rendah serta \textit{anti-icing} / \textit{de-icing}.\cite{Sha2021}
|
||||||
|
% \end{enumerate}
|
||||||
|
% \\
|
||||||
|
% & %Judul Jurnal
|
||||||
|
% Advances and development trends in eco-friendly pavements
|
||||||
|
|
||||||
|
% %for mult rows
|
||||||
|
|
||||||
|
% & %Author
|
||||||
|
% Aimin Sha, Zhuangzhuang Liu, Wei Jiang, Lin Qi, Liqun Hu, Wenxiu Jiao ,Diego Maria Barbieri
|
||||||
|
|
||||||
|
% %for mult rows
|
||||||
|
|
||||||
|
% & %Nama Jurnal
|
||||||
|
% Journal of Road Engineering 1 (2021)
|
||||||
|
|
||||||
|
% %for mult rows
|
||||||
|
|
||||||
|
% & %Sumber
|
||||||
|
% ScienceDirect
|
||||||
|
|
||||||
|
% %for mult rows
|
||||||
|
|
||||||
|
% & %Tahun
|
||||||
|
% 2021
|
||||||
|
|
||||||
|
% %for mult rows
|
||||||
|
|
||||||
|
% & %Tujuan penelitian
|
||||||
|
% Mengembangkan solusi teknis untuk mengatasi tantangan yang terkait dengan penciptaan infrastruktur hijau dan berkelanjutan, misalnya, pengurangan dampak lingkungan, peningkatan keselamatan lalu lintas, dan efisiensi transportasi, dll.\cite{Sha2021}
|
||||||
|
% &
|
||||||
|
% \begin{enumerate}[resume=enum]
|
||||||
|
% \item Teknologi ini dapat memecahkan beberapa tantangan utama yang terkait dengan konstruksi jalan dan lalu lintas (misalnya, kebisingan, efek pulau panas, dan pembangkitan polusi). Sebagian besar solusi saat ini hanya tersedia menampilkan satu fungsi ramah lingkungan pada satu waktu.\cite{Sha2021}
|
||||||
|
% \end{enumerate}
|
||||||
|
|
||||||
|
% %-----------5
|
||||||
|
% \\
|
||||||
|
% 5
|
||||||
|
|
||||||
|
% & %Judul Jurnal
|
||||||
|
% Micromobility injury events: Motor vehicle crashes and other transportation systems factors
|
||||||
|
|
||||||
|
% %for mult rows
|
||||||
|
|
||||||
|
% & %Author
|
||||||
|
% Kevin Fang
|
||||||
|
|
||||||
|
% %for mult rows
|
||||||
|
|
||||||
|
% & %Nama Jurnal
|
||||||
|
% Transportation Research Interdisciplinary Perspectives 14 (2022) 100574
|
||||||
|
|
||||||
|
% %for mult rows
|
||||||
|
|
||||||
|
% & %Sumber
|
||||||
|
% ScienceDirect
|
||||||
|
|
||||||
|
% %for mult rows
|
||||||
|
|
||||||
|
% & %Tahun
|
||||||
|
% 2022
|
||||||
|
|
||||||
|
% %for mult rows
|
||||||
|
|
||||||
|
% & %Tujuan penelitian
|
||||||
|
% Menginformasikan transportasi strategi kebijakan untuk mencoba dan meningkatkan kinerja keselamatan, Dengan cara mengeksplorasi keadaan di mana cedera pengendara mikromobilitas mengalami cederanya, dengan fokus pada faktor-faktor yang berkaitan dengan sistem transportasi.\cite{Fang2022}
|
||||||
|
% &
|
||||||
|
% \begin{enumerate} [series=enum]
|
||||||
|
% \item Kecelakaan kendaraan bermotor secara mengejutkan menjulang sebagai sesuatu yang kemungkinan adalah faktor umum dalam cedera mikromobilitas. Masalah perkerasan, konflik
|
||||||
|
% dengan pengguna non-otomatis, dan medan juga muncul sebagai faktor cedera yang terukur.\cite{Fang2022}
|
||||||
|
% \end{enumerate}
|
||||||
|
% \\
|
||||||
|
% & %Judul Jurnal
|
||||||
|
% Micromobility injury events: Motor vehicle crashes and other transportation systems factors
|
||||||
|
|
||||||
|
% %for mult rows
|
||||||
|
|
||||||
|
% & %Author
|
||||||
|
% Kevin Fang
|
||||||
|
|
||||||
|
% %for mult rows
|
||||||
|
|
||||||
|
% & %Nama Jurnal
|
||||||
|
% Transportation Research Interdisciplinary Perspectives 14 (2022) 100574
|
||||||
|
|
||||||
|
% %for mult rows
|
||||||
|
|
||||||
|
% & %Sumber
|
||||||
|
% ScienceDirect
|
||||||
|
|
||||||
|
% %for mult rows
|
||||||
|
|
||||||
|
% & %Tahun
|
||||||
|
% 2022
|
||||||
|
|
||||||
|
% %for mult rows
|
||||||
|
|
||||||
|
% & %Tujuan penelitian
|
||||||
|
% Menginformasikan transportasi strategi kebijakan untuk mencoba dan meningkatkan kinerja keselamatan, Dengan cara mengeksplorasi keadaan di mana cedera pengendara mikromobilitas mengalami cederanya, dengan fokus pada faktor-faktor yang berkaitan dengan sistem transportasi.\cite{Fang2022}
|
||||||
|
% &
|
||||||
|
% \begin{enumerate} [resume=enum]
|
||||||
|
% \item Di antara faktor-faktor yang berhubungan dengan transportasi, analisis regresi
|
||||||
|
% menunjukkan bahwa terluka dalam kecelakaan kendaraan bermotor atau di medan berbukit
|
||||||
|
% sesuai dengan kemungkinan yang lebih besar dari rawat inap dan cedera kepala.\cite{Fang2022}
|
||||||
|
% \end{enumerate}
|
||||||
|
% \\
|
||||||
|
% & %Judul Jurnal
|
||||||
|
% Micromobility injury events: Motor vehicle crashes and other transportation systems factors
|
||||||
|
|
||||||
|
% %for mult rows
|
||||||
|
|
||||||
|
% & %Author
|
||||||
|
% Kevin Fang
|
||||||
|
|
||||||
|
% %for mult rows
|
||||||
|
|
||||||
|
% & %Nama Jurnal
|
||||||
|
% Transportation Research Interdisciplinary Perspectives 14 (2022) 100574
|
||||||
|
|
||||||
|
% %for mult rows
|
||||||
|
|
||||||
|
% & %Sumber
|
||||||
|
% ScienceDirect
|
||||||
|
|
||||||
|
% %for mult rows
|
||||||
|
|
||||||
|
% & %Tahun
|
||||||
|
% 2022
|
||||||
|
|
||||||
|
% %for mult rows
|
||||||
|
|
||||||
|
% & %Tujuan penelitian
|
||||||
|
% Menginformasikan transportasi strategi kebijakan untuk mencoba dan meningkatkan kinerja keselamatan, Dengan cara mengeksplorasi keadaan di mana cedera pengendara mikromobilitas mengalami cederanya, dengan fokus pada faktor-faktor yang berkaitan dengan sistem transportasi.\cite{Fang2022}
|
||||||
|
% &
|
||||||
|
% \begin{enumerate} [resume=enum]
|
||||||
|
% \item Mitigasi yang berhasil yang memaksimalkan kinerja mode keselamatan mikromobilitas dapat membantu menarik dan mempertahankan pengguna dan menjaga kepercayaan dari pembuat kebijakan yang peduli keselamatan.\cite{Fang2022}
|
||||||
|
% \end{enumerate}
|
||||||
|
% \end{tabular}
|
||||||
|
\end{longtable}
|
||||||
|
% \end{table}
|
||||||
|
\end{landscape}
|
||||||
|
\clearpage
|
||||||
|
\pagenumbering{roman}
|
||||||
|
\setcounter{page}{2}
|
||||||
|
\thispagestyle{empty}
|
||||||
|
\printbibliography
|
||||||
|
|
||||||
|
\clearpage
|
||||||
|
\begin{titlepage}
|
||||||
|
\
|
||||||
|
\vfill
|
||||||
|
\centering\noindent \Huge{LAMPIRAN}
|
||||||
|
\vfill
|
||||||
|
\
|
||||||
|
\end{titlepage}
|
||||||
|
|
||||||
|
|
||||||
|
% \clearpage
|
||||||
|
% \thispagestyle{empty}
|
||||||
|
% \centering
|
||||||
|
% \frame{\includegraphics[page=1,scale=.7]{assets/1-s2.0-S2095756420300295-main.pdf}}
|
||||||
|
% \captionof{figure}{Halaman pertama jurnal pertama}
|
||||||
|
|
||||||
|
% \clearpage
|
||||||
|
% \thispagestyle{empty}
|
||||||
|
% \centering
|
||||||
|
% \frame{\includegraphics[page=1,scale=.7]{assets/1-s2.0-S2214509520300024-main.pdf}}
|
||||||
|
% \captionof{figure}{Halaman pertama jurnal kedua}
|
||||||
|
|
||||||
|
% \clearpage
|
||||||
|
% \thispagestyle{empty}
|
||||||
|
% \centering
|
||||||
|
% \frame{\includegraphics[page=1,scale=.7]{assets/1-s2.0-S2214509520300784-main.pdf}}
|
||||||
|
% \captionof{figure}{Halaman pertama jurnal ketiga}
|
||||||
|
|
||||||
|
% \clearpage
|
||||||
|
% \thispagestyle{empty}
|
||||||
|
% \centering
|
||||||
|
% \frame{\includegraphics[page=1,scale=.7]{assets/1-s2.0-S2097049821000044-main.pdf}}
|
||||||
|
% \captionof{figure}{Halaman pertama jurnal keempat}
|
||||||
|
|
||||||
|
% \clearpage
|
||||||
|
% \thispagestyle{empty}
|
||||||
|
% \centering
|
||||||
|
% \frame{\includegraphics[page=1,scale=.7]{assets/1-s2.0-S2590198222000379-main.pdf}}
|
||||||
|
% \captionof{figure}{Halaman pertama jurnal kelima}
|
||||||
|
\end{document}
|
||||||
Reference in New Issue
Block a user