Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
705424f
added example usage for importing of multiple files. Changed import g…
darkwraith Jun 4, 2017
e4b27db
Added arbin_dQdV plotting function. Added example to Qplot.
darkwraith Jun 4, 2017
394eb68
Added arbin_dQdV_multi plotting function to allow comparing dQ/dV bet…
darkwraith Jun 4, 2017
450f621
Add plotting function arbin_plotvp_multi for plotting the voltage pro…
darkwraith Jun 4, 2017
2c4d57e
Ran Roxygen document() to rebuild documentation/manuals.
darkwraith Jun 4, 2017
db79053
Updated arbinimport to allow for non-destructive normalization by sto…
darkwraith Jun 4, 2017
bc96cb2
Added manual information for new normalization options.
darkwraith Jun 4, 2017
c2032d3
Changed from dataframe to listfor the impored data in order to have t…
darkwraith Jun 4, 2017
364f490
Update arbin_plotvp to normalize data depending on user preference. P…
darkwraith Jun 4, 2017
352f672
Update arbin_plotvp_multi to normalize data, and plot with correct un…
darkwraith Jun 4, 2017
ff6c014
Update arbin_Qplot to properly handle normalization and plotting norm…
darkwraith Jun 4, 2017
1c67641
Add multiplot function to group multiple plots into one figure based …
darkwraith Jun 4, 2017
26a310c
Updated documentation and fixed naming of arbinimpot/arbin_import.
darkwraith Jun 4, 2017
cf41cc8
Fixed logic expression for setting norm units.
darkwraith Jun 4, 2017
ce9a75a
Change axis labels to shorten to Q dis/charge. Inputs need to be char…
darkwraith Jun 4, 2017
e785879
Provide error messages if user wants to normalize by variable that do…
darkwraith Jun 4, 2017
759e76b
fixed logic for formation of normunits in arbin_plotvp_multi.
darkwraith Jun 4, 2017
1a598ce
Generated manual files from Roxygen document().
darkwraith Jun 4, 2017
d7e35f0
Merge pull request #1 from darkwraith/normalize
darkwraith Jun 4, 2017
06e614a
add entire folder import tools and folder check functions to enable e…
darkwraith Jun 6, 2017
2c6bc92
Re-generated documentations.
darkwraith Jun 6, 2017
2047df7
Make file extension matching case insensitive with (?i).xls
darkwraith Jun 6, 2017
60063e4
During plotting convert to mAh as units suggest.
darkwraith Jun 12, 2017
65ffbd3
Fix variable from test variable to function variable.
darkwraith Jun 20, 2017
ad864c0
Merge pull request #2 from darkwraith/exportplots
darkwraith Jun 20, 2017
c0b52d3
Fix list name for arbin_plotvp_multi for logic to set correct normali…
darkwraith Jun 20, 2017
3f999b9
Fix errors in the quickplot documentation and rebuild the documentati…
darkwraith Jun 22, 2017
680c5d4
Fix arbinimport help documentation, units for area normalization. Pro…
darkwraith Jun 22, 2017
e68d971
Fix x axis labels for plotvp to Capacity/Specific Capacity/Areal Capa…
darkwraith Jun 22, 2017
9c563e1
Added ability to include title to all plots that only use one cell of…
darkwraith Jun 22, 2017
ddcfe87
Makes dQdV and dQdV_multi y scaling more robust. Defaults to set the …
darkwraith Jun 22, 2017
e9d0e77
Update description file. Bump version and add Jim as author.
darkwraith Jun 23, 2017
43c2cf7
Create LICENSE
darkwraith Jun 23, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .Rbuildignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
^.*\.Rproj$
^\.Rproj\.user$
14 changes: 11 additions & 3 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
Package: arbintools
Title: Matt Lacey's Arbin Importing and Plotting Functions
Version: 0.0.0.9000
Authors@R: person("Matt", "Lacey", email = "matthew.lacey@kemi.uu.se", role = c("aut", "cre"))
Version: 0.1.0
Authors@R:
c(person(given = "Matt",
family = "Lacey",
role = c("aut", "cre"),
email = "matthew.lacey@kemi.uu.se"),
person(given = "Jim",
family = "Benson",
role = "ctb",
email = "james.benson@gatech.edu"))
Description: A set of functions to handle importation and common plotting tasks for data obtained with Arbin battery cycling instruments using the MITS Pro software.
Depends:
R (>= 3.2.0)
License: CC0
LazyData: true
RoxygenNote: 5.0.1
RoxygenNote: 6.0.1
Imports: dplyr,
ggplot2,
reshape2,
Expand Down
674 changes: 674 additions & 0 deletions LICENSE

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
# Generated by roxygen2: do not edit by hand

export(arbin_Qplot)
export(arbin_dQdV)
export(arbin_dQdV_multi)
export(arbin_import)
export(arbin_import_folder)
export(arbin_import_folder_check)
export(arbin_import_raw)
export(arbin_plotvp)
export(arbin_plotvp_multi)
export(arbin_quickplot)
export(multiplot)
167 changes: 117 additions & 50 deletions R/import_functions.R
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
### Importing functions

#' arbin_import
#'
#'
#' This function takes an exported data file in Microsoft Excel format,
#' discards or includes certain data depending on the options chosen in the function,
#' and returns a list of two data frames: the complete raw data and an aggregated
Expand All @@ -12,91 +12,88 @@
#' @param energy Defaults to TRUE. Includes the (dis)charge energy variables from the data file if TRUE.
#' @param cycles Defaults to 100. Determines the maximum number of cycles to be considered when
#' aggregating the statistics dataset.
#' @param mass Defaults to NULL. If an active material mass is specified - in MILLIGRAMS - the
#' capacities in the raw and statistics data frames will be converted to mAh/g.
#' @param mass Defaults to NULL. If an active material mass is specified - in MILLIGRAMS, mg - it is stored
#' in the norm parameter for normalization options during plotting.
#' @param area Defaults to NULL. If an electrode area is specified - in SQUARE CENTIMETERS, cm^2 - it is stored
#' in the norm parameter for normalization options during plotting.
#' @param vol Defaults to NULL. If an active material volume is specified - in CUBIC CENTIMETERS, cm^3 - it is stored
#' in the norm parameter for normalization options during plotting.
#' @param meanE Defaults to FALSE. Will calculate a statistic for average charge and discharge voltage
#' if set to TRUE.
#' @keywords
#' @export
#' @examples
#' @examples
#' mydataset <- arbin_import("dataset.xlsx")
#' mydataset <- arbin_import("dataset.xlsx", step.time = FALSE, cycles = 200, mass = 2.55)
#' mydataset <- arbin_import("dataset.xlsx", step.time = FALSE, cycles = 200, mass = 2.55, area=1.267)
#' Batch import of multiple cells from list, useful for Qplot, plotvp_multi, dQdV_multi, etc.
#' l=lapply(1:length(cellfile),function(x) arbinimport(cellfile[x],cycles=100,mass=mass[x]))

arbin_import <- function(file, step.time = TRUE, energy = TRUE, cycles = 100, mass = NULL, meanE = FALSE) {

arbin_import<-function (file, step.time = TRUE, energy = TRUE, cycles = 100, mass = NULL, area = NULL ,
vol = NULL, meanE = FALSE)
{
require(readxl)
# All the "Channel*" sheets are read in. This function needs the readxl package.
l <- lapply(grep("Channel*", excel_sheets(file), value = TRUE),

# All the "Channel*" sheets are read in, excludes plot sheets. This function needs the readxl package.
l <- lapply(grep("Channel_\\d", excel_sheets(file), value = TRUE),
read_excel, path = file)

# The list from the previous step is unlisted into a single data frame
l <- do.call(rbind, l)

# A new data frame for raw data is created using selected parts of the data.
x <- data.frame(t = l$`Test_Time(s)`, # time (s)
step.n = l$Step_Index, # step number
cyc.n = l$Cycle_Index, # cycle number
I = l$`Current(A)`, # current (A)
E = l$`Voltage(V)`, # voltage (E)
Q.c = l$`Charge_Capacity(Ah)`, # charge capacity (Ah)
Q.c = l$`Charge_Capacity(Ah)`, # charge capacity (Ah)
Q.d = l$`Discharge_Capacity(Ah)` # discharge capacity (Ah)
)

# Step time is included if specified.
if(step.time == TRUE) {
x$step.t <- l$`Step_Time(s)` # step time (s)
}

# (Dis)charge energy is included if specified.
if(energy == TRUE) {
x$En.d <- l$`Discharge_Energy(Wh)` # discharge energy (Wh)
x$En.c <- l$`Charge_Energy(Wh)` # charge energy (Wh)
}

# Capacities are converted to mAh/g if active mass is specified.
if(!is.null(mass) == TRUE) {
x$Q.c <- x$Q.c * (1E6/mass)
x$Q.d <- x$Q.d * (1E6/mass)
}

# Energies, if present, are converted to Wh/kg if active mass is specified.
if(!is.null(mass) == TRUE & energy == TRUE) {
x$En.d <- x$En.d * (1E6/mass)
x$En.c <- x$En.c * (1E6/mass)
}


# Number of cycles to be included defaults to 100. In any case, the data is checked
# and incomplete last cycles are discarded.
cycles <- ifelse(max(x$cyc.n >= cycles), cycles, max(x$cyc.n) - 1)

# Data frame of aggregated statistics is constructed.
stats <- data.frame(
cyc.n = c(1:cycles),
Q.c = sapply(c(1:cycles), function(i) tail(x$Q.c[x$cyc.n == i], 1)),
Q.d = sapply(c(1:cycles), function(i) tail(x$Q.d[x$cyc.n == i], 1)),
CE = sapply(c(1:cycles), function(i) tail(x$Q.d[x$cyc.n == i], 1) / tail(x$Q.c[x$cyc.n == i], 1))
)

# Energy is included if specified.
if(energy == TRUE) {
stats$EE <- sapply(c(1:cycles), function(i) tail(x$En.d[x$cyc.n == i], 1) / tail(x$En.c[x$cyc.n == i], 1))
}

# Mean voltages are included if specified.
if(meanE == TRUE) {
stats$meanE.d <- sapply(c(1:cycles), function(i) mean(x$E[x$cyc.n == i & x$I < 0], 1))
stats$meanE.c <- sapply(c(1:cycles), function(i) mean(x$E[x$cyc.n == i & x$I > 0], 1))
}

# Raw and statistics data frames are returned as a list.
out <- list(raw = x, stats = stats)
#Save information for normalization into list.
#Allows plotting functions to perform normalization as needed instead of at import.
norm<-list(mass=mass, area=area, vol=vol)
# Raw, statistics, and normalization data frames are returned as a list.
out <- list(raw = x, stats = stats, norm = norm)
return(out)
}


#' arbin_import_raw
#'
#'
#' This function is a simplified version of arbin_import which does not output a separate
#' statistics data frame. Consequently the output is a data frame rather than a list.
#' @param file The filename, which must end in .xls or .xlsx.
Expand All @@ -106,48 +103,118 @@ arbin_import <- function(file, step.time = TRUE, energy = TRUE, cycles = 100, ma
#' capacities in the raw and statistics data frames will be converted to mAh/g.
#' @keywords
#' @export
#' @examples
#' @examples
#' mydataset <- arbin_import("dataset.xlsx")
#' mydataset <- arbin_import("dataset.xlsx", step.time = FALSE)

arbin_import_raw <- function(file, step.time = TRUE, energy = TRUE, mass = NULL) {
arbin_import_raw <- function(file, step.time = TRUE, energy = TRUE, mass = NULL, area = NULL , vol = NULL) {

require(readxl, quietly = TRUE)
l <- lapply(grep("Channel*", excel_sheets(file), value = TRUE),

l <- lapply(grep("Channel_\\d", excel_sheets(file), value = TRUE),
read_excel, path = file)

l <- do.call(rbind, l)

x <- data.frame(t = l$`Test_Time(s)`, # time (s)
step.n = l$Step_Index, # step number
cyc.n = l$Cycle_Index, # cycle number
I = l$`Current(A)`, # current (A)
E = l$`Voltage(V)`, # voltage (E)
Q.c = l$`Charge_Capacity(Ah)`, # charge capacity (Ah)
Q.c = l$`Charge_Capacity(Ah)`, # charge capacity (Ah)
Q.d = l$`Discharge_Capacity(Ah)` # discharge capacity (Ah)
)

if(step.time == TRUE) {
x$step.t <- l$`Step_Time(s)` # step time (s)
}

if(energy == TRUE) {
x$En.d <- l$`Discharge_Energy(Wh)` # discharge energy (Wh)
x$En.c <- l$`Charge_Energy(Wh)` # charge energy (Wh)
}

# if active mass is specified.=========================================
# Capacities are converted to mAh/g if active mass is specified.
if(!is.null(mass) == TRUE) {
x$Q.c <- x$Q.c * (1E6/mass)
x$Q.d <- x$Q.d * (1E6/mass)
}
# Energies, if present, are converted to Wh/kg if active mass is specified.

# Energies, if present, are converted to Wh/kg
if(!is.null(mass) == TRUE & energy == TRUE) {
x$En.d <- x$En.d * (1E6/mass)
x$En.c <- x$En.c * (1E6/mass)
}

# if area is specified.=========================================
# Capacities are converted to mAh/cm^2
if(!is.null(area) == TRUE) {
x$Q.c <- x$Q.c * (1/area)
x$Q.d <- x$Q.d * (1/area)
}
# Energies, if present, are converted to Wh/cm^2
if(!is.null(area) == TRUE & energy == TRUE) {
x$En.d <- x$En.d * (1/area)
x$En.c <- x$En.c * (1/area)
}
# if volume is specified.=========================================
# Capacities are converted to mAh/cm^3
if(!is.null(vol) == TRUE) {
x$Q.c <- x$Q.c * (1E3/vol)
x$Q.d <- x$Q.d * (1E3/vol)
}
# Energies, if present, are converted to Wh/cm^3
if(!is.null(vol) == TRUE & energy == TRUE) {
x$En.d <- x$En.d * (1/vol)
x$En.c <- x$En.c * (1/vol)
}

return(x)
}
}
#' arbin_import_folder
#'
#' This function is a simplified version of arbin_import which does not output a separate
#' statistics data frame. Consequently the output is a data frame rather than a list.
#' @param path The folder path, which must include .xls or .xlsx files produced by the arbin.
#' @param mass Defaults to NULL. A vector including the active masses (in MILLIGRAMS, mg) of all cells in the folder being imported.
#' Use arbin_import_folder_check to ensure correct order.
#' @param area Defaults to NULL. A vector including the area (in SQUARE CENTIMETERS, cm^2) of all cells in the folder being imported.
#' Use arbin_import_folder_check to ensure correct order.
#' @param vol Defaults to Null. A vector including the volume (in cubic CENTIMETERS, cm^3) of all cells in the folder being imported.
#' Use arbin_import_folder_check to ensure correct order.
#' @keywords
#' @export
#' @examples
#' mydataset <- arbin_import_folder(path)
#' mydataset <- arbin_import_folder()
arbin_import_folder <- function(path=".",mass=NULL, area=NULL, vol=NULL)
{
initfolder<-getwd()
setwd(path)
#collect the names of all of the xls,xlsx files in a folder
f<-list.files(path=path,pattern="(?i).xls")
#Import all the files using arbin import
l=lapply(1:length(f),function(x) arbin_import(f[x],mass=mass[x],area=area[x],vol=vol[x]))
setwd(initfolder)
return(l)

}

#' arbin_import_folder_check
#'
#' This function is a simplified version of arbin_import which does not output a separate
#' statistics data frame. Consequently the output is a data frame rather than a list.
#' @param path The folder path containing only data files from the arbin, which must end in .xls or .xlsx.
#' @keywords
#' @export
#' @examples
#' mydataset <- arbin_import_folder(path)
#' mydataset <- arbin_import_folder()
arbin_import_folder_check <- function(path=".")
{
initfolder<-getwd()
setwd(path)
#collect the names of all of the xls,xlsx files in a folder
f<-list.files(path=path,pattern="(?i).xls")
setwd(initfolder)
return(f)
}
Loading