This workflow automates the complete MILK Ti-6Al-4V analysis.
| Phase | Description |
|---|---|
| Phase 1 | Dataset Understanding and Preparation |
| Phase 2 | Exploratory Diffraction Analysis |
| Phase 3 | Principal Component Analysis (PCA) |
| Phase 4 | Peak Tracking and Region Identification |
| Phase 5 | Similarity and Transition Analysis |
| Phase 6 | Automated Peak Ranking |
| Phase 7 | Full-Pattern PLS Prediction of Phase Composition |
| Phase 8 | Phase Evolution and Interpretation |
| Phase 9 | Window-Based PLS Prediction of Phase Composition |
| Phase 10 | Experimental Condition Integration (Future) |
| Phase 11 | Microstructural Evolution Analysis (Future) |
# User Settings
data_dir <- "C:/Users/gerar/MILK/examples/Synchrotron/sequential_refinement/my_scripts"
# Create output folders automatically
dir.create(
"Figures",
showWarnings = FALSE
)
dir.create(
"Results",
showWarnings = FALSE
)
# Input files
XFILE <- file.path(
data_dir,
"X_matrix.csv"
)
YFILE <- file.path(
data_dir,
"Y_matrix.csv"
)
# Verify files exist
if(!file.exists(XFILE)){
stop("X_matrix.csv not found.")
}
if(!file.exists(YFILE)){
stop("Y_matrix.csv not found.")
}
cat("Input files verified.\n")
## Input files verified.
windows <- list(
W1 = c(4.0,4.2),
W2 = c(4.6,4.8),
W3 = c(6.8,7.1),
W4 = c(9.0,9.3),
W5 = c(10.4,10.6)
)
load_milk_data <- function(XFILE,YFILE){
raw <- read.csv(
XFILE,
header = FALSE,
check.names = FALSE,
stringsAsFactors = FALSE
)
theta <- as.numeric(
unlist(raw[1,-1])
)
run_names <- raw[-1,1]
X <- raw[-1,-1]
X <- apply(
X,
2,
as.numeric
)
X <- as.matrix(X)
rownames(X) <- run_names
Y <- read.csv(
YFILE,
check.names = FALSE,
stringsAsFactors = FALSE
)
list(
X = X,
Y = Y,
theta = theta
)
}
build_phase_dataset <- function(Y){
data.frame(
Run = Y$Title,
Alpha = Y[[4]],
Steel = Y[[13]],
Beta = Y[[21]]
)
}
assign_phase_state <- function(alpha,beta){
case_when(
alpha > 70 ~ "Alpha Rich",
beta > 70 ~ "Beta Rich",
TRUE ~ "Mixed Alpha-Beta"
)
}
normalize <- function(x){
(x - min(x)) /
(max(x) - min(x))
}
milk <- load_milk_data(
XFILE,
YFILE
)
X <- milk$X
Y <- milk$Y
theta <- milk$theta
phase_data <- build_phase_dataset(Y)
Construct X and Y matrices and verify data integrity.
cat(
"Number of Runs:",
nrow(X),
"\n"
)
## Number of Runs: 28
cat(
"Number of Variables:",
ncol(X),
"\n"
)
## Number of Variables: 1500
cat(
"Missing Values in X:",
sum(is.na(X)),
"\n"
)
## Missing Values in X: 0
cat(
"Missing Values in Y:",
sum(is.na(Y)),
"\n"
)
## Missing Values in Y: 0
head(phase_data)
## Run Alpha Steel Beta
## 1 run000Ti64_test_data03 82.70725 17.29275 0.00000
## 2 run001Ti64_test_data03 82.65025 17.34976 0.00000
## 3 run002Ti64_test_data03 82.49252 17.50747 0.00000
## 4 run003Ti64_test_data03 82.64799 17.35202 0.00000
## 5 run004Ti64_test_data03 70.97442 16.95435 12.07123
## 6 run005Ti64_test_data03 69.17553 17.08608 13.73840
summary(phase_data)
## Run Alpha Steel Beta
## Length :28 Min. : 0.00 Min. : 7.101 Min. : 0.00
## N.unique :28 1st Qu.: 0.00 1st Qu.:14.554 1st Qu.:14.72
## N.blank : 0 Median :62.76 Median :16.701 Median :20.92
## Min.nchar:22 Mean :43.74 Mean :15.868 Mean :40.39
## Max.nchar:22 3rd Qu.:64.87 3rd Qu.:17.431 3rd Qu.:85.45
## Max. :82.71 Max. :21.520 Max. :92.90
Visualize diffraction-pattern evolution across runs.
plot(
theta,
X[1,],
type = "l",
lwd = 2,
col = "black",
xlab = expression(2*theta),
ylab = "Intensity",
main = rownames(X)[1]
)
plot(
theta,
X[1,],
type = "l",
lwd = 2,
col = "black",
xlab = expression(2*theta),
ylab = "Intensity",
main = "First Four Runs"
)
lines(theta,X[2,],col="red",lwd=2)
lines(theta,X[3,],col="blue",lwd=2)
lines(theta,X[4,],col="green",lwd=2)
legend(
"topright",
legend = rownames(X)[1:4],
col = c("black","red","blue","green"),
lwd = 2
)
matplot(
theta,
t(X),
type = "l",
lty = 1,
col = rainbow(nrow(X)),
xlab = expression(2*theta),
ylab = "Intensity",
main = "All Diffraction Patterns"
)
offset <- 20
plot(
theta,
X[1,],
type = "l",
lwd = 1.5,
xlab = expression(2*theta),
ylab = "Offset Intensity",
main = "Waterfall Plot"
)
for(i in 2:nrow(X)){
lines(
theta,
X[i,] + (i-1)*offset,
col = i,
lwd = 1
)
}
plot(
theta,
X[2,] - X[1,],
type = "l",
lwd = 2,
col = "red",
xlab = expression(2*theta),
ylab = expression(Delta*Intensity),
main = "Run001 - Run000"
)
abline(h=0,lty=2)
Identify dominant diffraction-state evolution.
pca <- prcomp(
X,
center = TRUE,
scale. = TRUE
)
var_exp <- pca$sdev^2 /
sum(pca$sdev^2)
plot(
var_exp,
type = "b",
pch = 19,
xlab = "Principal Component",
ylab = "Variance Explained",
main = "Scree Plot"
)
plot(
cumsum(var_exp),
type = "b",
pch = 19,
xlab = "Principal Component",
ylab = "Cumulative Variance Explained",
main = "Cumulative Variance"
)
abline(
h = 0.90,
lty = 2,
col = "red"
)
plot(
pca$x[,1],
pca$x[,2],
pch = 19,
xlab = "PC1",
ylab = "PC2",
main = "PCA Scores"
)
text(
pca$x[,1],
pca$x[,2],
labels = rownames(X),
pos = 3,
cex = 0.7
)
plot(
pca$x[,1],
pca$x[,2],
type = "b",
pch = 19,
xlab = "PC1",
ylab = "PC2",
main = "PCA Trajectory"
)
text(
pca$x[,1],
pca$x[,2],
labels = rownames(X),
pos = 3,
cex = 0.7
)
plot(
theta,
pca$rotation[,1],
type = "l",
lwd = 2,
col = "blue",
xlab = expression(2*theta),
ylab = "Loading",
main = "PC1 Loadings"
)
abline(h=0,lty=2)
plot(
theta,
pca$rotation[,2],
type = "l",
lwd = 2,
col = "red",
xlab = expression(2*theta),
ylab = "Loading",
main = "PC2 Loadings"
)
abline(h=0,lty=2)
# PHASE 4: PEAK TRACKING AND REGION IDENTIFICATION
Track peak position, peak intensity, peak area, and peak width (FWHM) for all PCA-selected diffraction windows.
peak_results <- data.frame()
for(w in seq_along(windows)){
rng <- windows[[w]]
idx <- which(
theta >= rng[1] &
theta <= rng[2]
)
theta_window <- theta[idx]
X_window <- X[,idx]
for(i in 1:nrow(X_window)){
intensity <- X_window[i,]
peak_index <- which.max(intensity)
peak_position <- theta_window[peak_index]
peak_intensity <- max(intensity)
peak_area <- sum(intensity)
half_max <- peak_intensity/2
above_half <- which(
intensity >= half_max
)
if(length(above_half) >= 2){
peak_fwhm <-
theta_window[max(above_half)] -
theta_window[min(above_half)]
} else {
peak_fwhm <- NA
}
peak_results <- rbind(
peak_results,
data.frame(
Window = names(windows)[w],
Run = rownames(X_window)[i],
Peak_Position = peak_position,
Peak_Intensity = peak_intensity,
Peak_Area = peak_area,
Peak_FWHM = peak_fwhm
)
)
}
}
head(peak_results)
## Window Run Peak_Position Peak_Intensity Peak_Area Peak_FWHM
## 1 W1 run000_ Intensity 4.153467 259.3615 3766.498 0.0601333
## 2 W1 run001_ Intensity 4.153467 255.9989 3716.876 0.0601333
## 3 W1 run002_ Intensity 4.153467 257.6476 3745.153 0.0601333
## 4 W1 run003_ Intensity 4.153467 257.9053 3745.285 0.0601333
## 5 W1 run004_ Intensity 4.115200 240.1876 3464.321 0.0492000
## 6 W1 run005_ Intensity 4.115200 245.8973 3545.128 0.0492000
ggplot(
peak_results,
aes(
x = seq_along(Run),
y = Peak_Intensity,
color = Window,
group = Window
)
)+
geom_line()+
geom_point()+
labs(
title = "Peak Intensity Evolution",
x = "Run Number",
y = "Peak Intensity"
)
ggplot(
peak_results,
aes(
x = seq_along(Run),
y = Peak_Position,
color = Window,
group = Window
)
)+
geom_line()+
geom_point()+
labs(
title = "Peak Position Evolution",
x = "Run Number",
y = "Peak Position"
)
ggplot(
peak_results,
aes(
x = seq_along(Run),
y = Peak_Area,
color = Window,
group = Window
)
)+
geom_line()+
geom_point()+
labs(
title = "Peak Area Evolution",
x = "Run Number",
y = "Peak Area"
)
ggplot(
peak_results,
aes(
x = seq_along(Run),
y = Peak_FWHM,
color = Window,
group = Window
)
)+
geom_line()+
geom_point()+
labs(
title = "Peak Width Evolution",
x = "Run Number",
y = "FWHM"
)
Determine whether transition regions can be identified automatically using similarity and distance metrics.
reference <- X[1,]
pearson_similarity <- apply(
X,
1,
function(x)
cor(reference,x)
)
euclidean_distance <- apply(
X,
1,
function(x)
sqrt(sum((x-reference)^2))
)
cosine_similarity <- apply(
X,
1,
function(x){
sum(reference*x) /
(
sqrt(sum(reference^2)) *
sqrt(sum(x^2))
)
}
)
consecutive_change <- rep(
NA,
nrow(X)
)
for(i in 2:nrow(X)){
consecutive_change[i] <-
sqrt(
sum(
(X[i,]-X[i-1,])^2
)
)
}
plot(
pearson_similarity,
type = "b",
pch = 19,
xlab = "Run Number",
ylab = "Pearson Correlation",
main = "Similarity to Run000"
)
abline(
h = mean(pearson_similarity),
lty = 2
)
plot(
euclidean_distance,
type = "b",
pch = 19,
xlab = "Run Number",
ylab = "Euclidean Distance",
main = "Distance from Run000"
)
plot(
cosine_similarity,
type = "b",
pch = 19,
xlab = "Run Number",
ylab = "Cosine Similarity",
main = "Cosine Similarity"
)
plot(
consecutive_change,
type = "b",
pch = 19,
xlab = "Run Number",
ylab = "Pattern Change",
main = "Consecutive Run Changes"
)
The combined PCA, correlation, cosine similarity, Euclidean distance, and consecutive-change analyses should be used to assess evidence for the reversible diffraction pathway:
A → B → C → B → A
Automatically rank diffraction windows according to their contribution to diffraction evolution.
ranking_results <- data.frame()
for(w in seq_along(windows)){
rng <- windows[[w]]
idx <- which(
theta >= rng[1] &
theta <= rng[2]
)
loading_score <- max(
abs(
pca$rotation[idx,1]
)
)
temp <- peak_results[
peak_results$Window ==
names(windows)[w],
]
ranking_results <- rbind(
ranking_results,
data.frame(
Window = names(windows)[w],
Loading_Score = loading_score,
Intensity_SD =
sd(temp$Peak_Intensity),
Area_SD =
sd(temp$Peak_Area),
Position_SD =
sd(temp$Peak_Position),
FWHM_SD =
sd(
temp$Peak_FWHM,
na.rm = TRUE
)
)
)
}
ranking_results
## Window Loading_Score Intensity_SD Area_SD Position_SD FWHM_SD
## 1 W1 0.02962684 97.516936 923.3300 0.026670889 0.06795714
## 2 W2 0.02958119 463.315714 4805.2992 0.032949120 0.07208287
## 3 W3 0.02970296 13.737580 257.2323 0.001948049 0.01249253
## 4 W4 0.02969446 11.037415 354.5706 0.039737797 0.01906608
## 5 W5 0.02971677 5.902495 177.3840 0.080026580 0.00000000
ranking <- ranking_results
ranking$Loading_Norm <-
normalize(
ranking$Loading_Score
)
ranking$Intensity_Norm <-
normalize(
ranking$Intensity_SD
)
ranking$Area_Norm <-
normalize(
ranking$Area_SD
)
ranking$Position_Norm <-
normalize(
ranking$Position_SD
)
ranking$FWHM_Norm <-
normalize(
ranking$FWHM_SD
)
ranking$Importance_Score <-
ranking$Loading_Norm +
ranking$Intensity_Norm +
ranking$Area_Norm +
ranking$Position_Norm +
ranking$FWHM_Norm
ranking <- ranking[
order(
ranking$Importance_Score,
decreasing = TRUE
),
]
ranking
## Window Loading_Score Intensity_SD Area_SD Position_SD FWHM_SD
## 2 W2 0.02958119 463.315714 4805.2992 0.032949120 0.07208287
## 5 W5 0.02971677 5.902495 177.3840 0.080026580 0.00000000
## 1 W1 0.02962684 97.516936 923.3300 0.026670889 0.06795714
## 4 W4 0.02969446 11.037415 354.5706 0.039737797 0.01906608
## 3 W3 0.02970296 13.737580 257.2323 0.001948049 0.01249253
## Loading_Norm Intensity_Norm Area_Norm Position_Norm FWHM_Norm
## 2 0.0000000 1.00000000 1.00000000 0.3970499 1.0000000
## 5 1.0000000 0.00000000 0.00000000 1.0000000 0.0000000
## 1 0.3367132 0.20028814 0.16118404 0.3166407 0.9427641
## 4 0.8353951 0.01122600 0.03828649 0.4839967 0.2645022
## 3 0.8981312 0.01712912 0.01725363 0.0000000 0.1733078
## Importance_Score
## 2 3.397050
## 5 2.000000
## 1 1.957590
## 4 1.633406
## 3 1.105822
ranking_display <- data.frame(
Rank = 1:nrow(ranking),
Window = ranking$Window,
Importance_Score =
round(
ranking$Importance_Score,
3
)
)
kable(
ranking_display
)
| Rank | Window | Importance_Score |
|---|---|---|
| 1 | W2 | 3.397 |
| 2 | W5 | 2.000 |
| 3 | W1 | 1.958 |
| 4 | W4 | 1.633 |
| 5 | W3 | 1.106 |
barplot(
ranking$Importance_Score,
names.arg = ranking$Window,
las = 2,
col = "steelblue",
ylab = "Importance Score",
main = "Automated Peak Ranking"
)
head(
ranking_display,
n = 3
)
## Rank Window Importance_Score
## 1 1 W2 3.397
## 2 2 W5 2.000
## 3 3 W1 1.958
Determine whether the complete diffraction pattern can predict:
using PLS regression.
X_df <- as.data.frame(X)
fit_pls <- function(response){
dat <- data.frame(
Response = response,
X_df
)
model <- plsr(
Response ~ .,
data = dat,
scale = TRUE,
validation = "LOO"
)
pred <- as.vector(
predict(
model,
ncomp = 5
)
)
r2 <- cor(
response,
pred
)^2
rmse <- sqrt(
mean(
(response - pred)^2
)
)
list(
model = model,
pred = pred,
r2 = r2,
rmse = rmse
)
}
alpha_model <- fit_pls(
phase_data$Alpha
)
beta_model <- fit_pls(
phase_data$Beta
)
steel_model <- fit_pls(
phase_data$Steel
)
full_pattern_results <- data.frame(
Phase = c(
"Alpha",
"Beta",
"Steel"
),
R2 = c(
alpha_model$r2,
beta_model$r2,
steel_model$r2
),
RMSE = c(
alpha_model$rmse,
beta_model$rmse,
steel_model$rmse
)
)
kable(
full_pattern_results,
digits = 4
)
| Phase | R2 | RMSE |
|---|---|---|
| Alpha | 0.9984 | 1.3451 |
| Beta | 0.9980 | 1.5919 |
| Steel | 0.9684 | 0.6056 |
plot(
phase_data$Alpha,
alpha_model$pred,
pch = 19,
xlab = "Measured Alpha %",
ylab = "Predicted Alpha %",
main = "Alpha Prediction"
)
abline(
0,
1,
col = "red",
lwd = 2
)
plot(
phase_data$Beta,
beta_model$pred,
pch = 19,
xlab = "Measured Beta %",
ylab = "Predicted Beta %",
main = "Beta Prediction"
)
abline(
0,
1,
col = "red",
lwd = 2
)
plot(
phase_data$Steel,
steel_model$pred,
pch = 19,
xlab = "Measured Steel %",
ylab = "Predicted Steel %",
main = "Steel Prediction"
)
abline(
0,
1,
col = "red",
lwd = 2
)
Interpret diffraction evolution in terms of phase evolution.
window_df <- data.frame(
Run = phase_data$Run
)
for(i in seq_along(windows)){
rng <- windows[[i]]
cols <- which(
theta >= rng[1] &
theta <= rng[2]
)
window_df[[paste0("W",i,"_Mean")]] <-
rowMeans(X[,cols])
window_df[[paste0("W",i,"_Max")]] <-
apply(X[,cols],1,max)
window_df[[paste0("W",i,"_Area")]] <-
rowSums(X[,cols])
}
phase_results <- left_join(
phase_data,
window_df,
by = "Run"
)
window_cols <- names(phase_results)[
grepl("_Max",names(phase_results))
]
corr_summary <- data.frame()
for(w in window_cols){
corr_summary <- rbind(
corr_summary,
data.frame(
Window = w,
Alpha_r = cor(
phase_results[[w]],
phase_results$Alpha
),
Beta_r = cor(
phase_results[[w]],
phase_results$Beta
),
Steel_r = cor(
phase_results[[w]],
phase_results$Steel
)
)
)
}
kable(
corr_summary,
digits = 3
)
| Window | Alpha_r | Beta_r | Steel_r |
|---|---|---|---|
| W1_Max | 0.984 | -0.987 | 0.724 |
| W2_Max | 0.969 | -0.962 | 0.610 |
| W3_Max | 0.166 | -0.188 | 0.349 |
| W4_Max | -0.747 | 0.782 | -0.894 |
| W5_Max | -0.407 | 0.376 | 0.040 |
phase_results$PhaseState <-
assign_phase_state(
phase_results$Alpha,
phase_results$Beta
)
table(
phase_results$PhaseState
)
##
## Alpha Rich Beta Rich Mixed Alpha-Beta
## 5 10 13
ggplot(
phase_results,
aes(
x = Run,
y = 1,
fill = PhaseState
)
)+
geom_tile()+
scale_fill_manual(
values = c(
"Alpha Rich" = "blue",
"Mixed Alpha-Beta" = "gold",
"Beta Rich" = "red"
)
)+
theme(
axis.text.y =
element_blank(),
axis.ticks.y =
element_blank()
)+
labs(
title =
"Run-Based Phase State Map"
)
n <- nrow(phase_results)
turn_point <- 14
phase_results$TempCycle <- c(
seq(
0,
1,
length.out = turn_point
),
seq(
1,
0,
length.out =
n - turn_point + 1
)[-1]
)
phase_long <-
phase_results %>%
select(
Run,
Alpha,
Beta,
Steel,
TempCycle
) %>%
pivot_longer(
c(
Alpha,
Beta,
Steel
),
names_to = "Phase",
values_to = "Fraction"
)
ggplot(
phase_long,
aes(
TempCycle,
Fraction,
color = Phase
)
)+
geom_line(
linewidth = 1.2
)+
geom_point(
size = 2
)+
labs(
title =
"Phase Evolution vs Temperature Cycle"
)
Determine whether diagnostic diffraction windows can reproduce full-pattern predictive performance.
window_predictors <-
data.frame(
Run = phase_data$Run
)
for(i in seq_along(windows)){
rng <- windows[[i]]
cols <- which(
theta >= rng[1] &
theta <= rng[2]
)
window_predictors[[names(windows)[i]]] <-
rowMeans(
X[,cols,drop=FALSE]
)
}
pls_data <- left_join(
phase_data,
window_predictors,
by = "Run"
)
evaluate_pls <- function(
Xvars,
yvar,
data
){
form <- as.formula(
paste(
yvar,
"~",
paste(
Xvars,
collapse = "+"
)
)
)
model <- plsr(
form,
data = data,
validation = "LOO",
scale = TRUE
)
pred <- as.vector(
predict(
model,
ncomp =
model$ncomp
)
)
obs <- data[[yvar]]
r2 <- cor(
obs,
pred
)^2
rmse <- sqrt(
mean(
(obs-pred)^2
)
)
data.frame(
Predictors =
paste(
Xvars,
collapse = ", "
),
Target = yvar,
R2 = r2,
RMSE = rmse
)
}
predictor_sets <- list(
W1 = c("W1"),
W2 = c("W2"),
W4 = c("W4"),
W1_W2 = c(
"W1",
"W2"
),
W1_W2_W4 = c(
"W1",
"W2",
"W4"
),
All_Windows = c(
"W1",
"W2",
"W3",
"W4",
"W5"
)
)
alpha_results <- bind_rows(
lapply(
predictor_sets,
evaluate_pls,
yvar = "Alpha",
data = pls_data
),
.id = "Model"
)
beta_results <- bind_rows(
lapply(
predictor_sets,
evaluate_pls,
yvar = "Beta",
data = pls_data
),
.id = "Model"
)
steel_results <- bind_rows(
lapply(
predictor_sets,
evaluate_pls,
yvar = "Steel",
data = pls_data
),
.id = "Model"
)
window_results <-
bind_rows(
alpha_results,
beta_results,
steel_results
)
kable(
window_results,
digits = 4
)
| Model | Predictors | Target | R2 | RMSE |
|---|---|---|---|---|
| W1 | W1 | Alpha | 0.9623 | 6.4626 |
| W2 | W2 | Alpha | 0.9729 | 5.4781 |
| W4 | W4 | Alpha | 0.7627 | 16.2142 |
| W1_W2 | W1, W2 | Alpha | 0.9839 | 4.2252 |
| W1_W2_W4 | W1, W2, W4 | Alpha | 0.9850 | 4.0813 |
| All_Windows | W1, W2, W3, W4, W5 | Alpha | 0.9893 | 3.4397 |
| W1 | W1 | Beta | 0.9708 | 6.0951 |
| W2 | W2 | Beta | 0.9606 | 7.0870 |
| W4 | W4 | Beta | 0.7482 | 17.9079 |
| W1_W2 | W1, W2 | Beta | 0.9819 | 4.7987 |
| W1_W2_W4 | W1, W2, W4 | Beta | 0.9821 | 4.7726 |
| All_Windows | W1, W2, W3, W4, W5 | Beta | 0.9879 | 3.9239 |
| W1 | W1 | Steel | 0.5445 | 2.2991 |
| W2 | W2 | Steel | 0.3975 | 2.6442 |
| W4 | W4 | Steel | 0.2801 | 2.8904 |
| W1_W2 | W1, W2 | Steel | 0.6549 | 2.0011 |
| W1_W2_W4 | W1, W2, W4 | Steel | 0.8735 | 1.2117 |
| All_Windows | W1, W2, W3, W4, W5 | Steel | 0.8976 | 1.0902 |
ggplot(
window_results,
aes(
x = Model,
y = R2,
fill = Target
)
)+
geom_col(
position = "dodge"
)+
labs(
title =
"Window-Based PLS Performance",
y = expression(R^2)
)
Develop phase-boundary interpretations and relate diffraction-state transitions to experimental conditions.
Relate phase evolution to microstructural evolution.
kable(
full_pattern_results,
digits = 4,
caption =
"Full Pattern PLS Results"
)
| Phase | R2 | RMSE |
|---|---|---|
| Alpha | 0.9984 | 1.3451 |
| Beta | 0.9980 | 1.5919 |
| Steel | 0.9684 | 0.6056 |
head(
ranking_display,
n = 5
)
## Rank Window Importance_Score
## 1 1 W2 3.397
## 2 2 W5 2.000
## 3 3 W1 1.958
## 4 4 W4 1.633
## 5 5 W3 1.106
PCA identified multiple diffraction states.
Similarity metrics supported a reversible pathway:
A → B → C → B → A
Peak tracking identified highly variable diffraction regions.
Automated ranking objectively prioritized diffraction windows.
Full-pattern PLS accurately predicted phase fractions.
Diagnostic windows revealed relationships between diffraction evolution and phase evolution.
Run-based classification identified:
Window-based PLS demonstrated that a reduced set of diffraction windows retained substantial predictive information.
Future work should integrate:
to develop physically based phase-boundary interpretations.
write.csv(
peak_results,
"PeakResults.csv",
row.names = FALSE
)
write.csv(
ranking,
"WindowRanking.csv",
row.names = FALSE
)
write.csv(
full_pattern_results,
"FullPatternPLS.csv",
row.names = FALSE
)
write.csv(
window_results,
"WindowPLS.csv",
row.names = FALSE
)
write.csv(
phase_results,
"PhaseEvolution.csv",
row.names = FALSE
)
`