Code Monkey home page Code Monkey logo

fips's Introduction

Travis build status codecov DOI

Fatigue Impairment Prediction Suite (FIPS)

FIPSLOGO

If you are measure sleep behaviour or want to predict fatigue, this package probably can help.

FIPS is an R package that provides researchers and practitioners with a comprehensive set of functions for applying and simulating from bio-mathematical models (BMMs) of fatigue.

FIPS includes a set of functions for transforming sleep and actigraphy data to the data frame structure required for executing BMM simulations (called a FIPS_df). Importantly, FIPS includes a set of functions for simulating from and interpreting several forms of BMM, including the Unified Model and Three Process Model. All models are extendable and include customisable parameters. The core features of FIPS leverage R's flexible S3 class system, making extensions straightforward.

Installation

We have no plans for a CRAN submission. To install the latest version of FIPS:

# install.packages('remotes') # if remotes not installed
remotes::install_github("humanfactors/FIPS")

Core Features Example

Detailed information regarding the FIPS data formats can be found in the "FIPS Simulation Walkthrough Vignette".

If you require a more manual user-interface to generate the FIPS-df, we have a web application that may help you generate the input CSV: https://github.com/Akhil-Eaga/FIPS-Data-Entry-System.

Step 1: Prior to simulation, FIPS requires sleep history data to be in a special format, called a FIPS_df which contains all the information required for modelling (e.g., time awake, time asleep). This can be created with parse_sleepwake_sequence or parse_sleeptimes.

my_FIPS_dataframe = FIPS::parse_sleepwake_sequence(
  seq = unit_sequence,  # A binary (1,0) vector 
  epoch = 5,            # Epoch in minutes of vector
  series.start = as.POSIXct("2020-05-21 08:00:00"))

Step 2: To run a model simulation, you use FIPS_simulate, which returns a FIPS_simulation with all model predictions/forecasts generated in the corresponding columns. Note that the formula argument is optional, and sensible defaults will be used if omitted.

# Run a simulation with the three process model
TPM.simulation.results = FIPS::FIPS_simulate(
  FIPS_df = my_FIPS_dataframe,   # A FIPS_df
  modeltype = "TPM",             # Three Process Model
  pvec = TPM_make_pvec()         # Default parameter vector
  # formula = alertness ~ s + c + u + w  # An optional formula for output
)

# Run a simulation with the unified model
unified.simulation.results = FIPS::FIPS_simulate(
FIPS_df = my_FIPS_dataframe,   # A FIPS_df
modeltype = "unified",         # Unified model
pvec = unified_make_pvec()     # Default parameter vector
)  
$ print(TPM.simulation.results)
> ---------
> Model Type: TPM 
> Epoch Value: 5 minutes 
> Simulation duration: 60 hours 
> Time points: 721 
> Parameters used (pvec input): ...[Suppressed for README]...
> For descriptions of these parameters, inspect:  help(FIPS::TPM_make_pvec) 
> ---------
> # A tibble: 721 x 10
>    datetime             time wake_status sim_hours     s     c     w        u   KSS alertness
>    <dttm>              <dbl> <lgl>           <dbl> <dbl> <dbl> <dbl>    <dbl> <dbl>     <dbl>
>  1 2020-05-21 08:00:00  8    TRUE           0       7.96 -1.67 -5.72 -0.00274 10.3       6.28
>  2 2020-05-21 08:05:00  8.08 TRUE           0.0833  7.94 -1.63 -5.04 -0.00549  9.84      6.31
>  3 2020-05-21 08:10:00  8.17 TRUE           0.167   7.93 -1.59 -4.45 -0.00919  9.47      6.33
>  4 2020-05-21 08:15:00  8.25 TRUE           0.25    7.91 -1.55 -3.92 -0.0138   9.14      6.35
>  5 2020-05-21 08:20:00  8.33 TRUE           0.333   7.89 -1.50 -3.46 -0.0194   8.85      6.37
>  6 2020-05-21 08:25:00  8.42 TRUE           0.417   7.88 -1.46 -3.05 -0.0258   8.59      6.39
>  7 2020-05-21 08:30:00  8.5  TRUE           0.5     7.86 -1.42 -2.69 -0.0332   8.36      6.41
>  8 2020-05-21 08:35:00  8.58 TRUE           0.583   7.85 -1.37 -2.37 -0.0415   8.16      6.43
>  9 2020-05-21 08:40:00  8.67 TRUE           0.667   7.83 -1.32 -2.09 -0.0506   7.98      6.46
> 10 2020-05-21 08:45:00  8.75 TRUE           0.75    7.81 -1.28 -1.84 -0.0606   7.82      6.48
> # ... with 711 more rows
$ print(unified.simulation.results)
> ---------
> Model Type: unified 
> Epoch Value: 5 minutes 
> Simulation duration: 60 hours 
> Time points: 721 
> Parameters used (pvec input): ...[Suppressed for README]...
> For descriptions of these parameters, inspect:  help(FIPS::unified_make_pvec) 
> ---------
> # A tibble: 721 x 9
>    datetime             time wake_status sim_hours      s      l     c     w fatigue
>    <dttm>              <dbl> <lgl>           <dbl>  <dbl>  <dbl> <dbl> <dbl>   <dbl>
>  1 2020-05-21 08:00:00  8    TRUE           0      0      0      0.335 1.14     1.38
>  2 2020-05-21 08:05:00  8.08 TRUE           0.0833 0.0502 0.0206 0.320 1.10     1.37
>  3 2020-05-21 08:10:00  8.17 TRUE           0.167  0.100  0.0412 0.305 1.06     1.36
>  4 2020-05-21 08:15:00  8.25 TRUE           0.25   0.150  0.0618 0.291 1.02     1.35
>  5 2020-05-21 08:20:00  8.33 TRUE           0.333  0.200  0.0824 0.276 0.978    1.34
>  6 2020-05-21 08:25:00  8.42 TRUE           0.417  0.250  0.103  0.261 0.941    1.33
>  7 2020-05-21 08:30:00  8.5  TRUE           0.5    0.300  0.123  0.247 0.906    1.32
>  8 2020-05-21 08:35:00  8.58 TRUE           0.583  0.349  0.144  0.232 0.872    1.31
>  9 2020-05-21 08:40:00  8.67 TRUE           0.667  0.399  0.164  0.218 0.839    1.30
> 10 2020-05-21 08:45:00  8.75 TRUE           0.75   0.448  0.185  0.204 0.807    1.29
> # ... with 711 more rows

Step 3: You now can access printing, summary and plot methods for the FIPS_simulation object. A detailed tutorial of the plotting functionality for FIPS is provided in the vignettes.

plot(TPM.simulation.results)
summary(TPM.simulation.results)
print(TPM.simulation.results)

What are BMMs?

BMMs are a class of biological phenomenological models which are used to predict the neuro-behavioural outcomes of fatigue (e.g., alertness, performance) using sleep-wake history. There are several different BMM implementations, but most have their roots in Borbély's (1982) two process model which stipulates that sleepiness/performance impairment functions in response to two processes: a circadian process and a homeostatic process. BMMs enable hypothesis testing of the latent factors underlying the relationships between sleep, fatigue, and human performance. For example, they enable researchers to estimate the relative contributions of homeostatic processes on fatigue, relative to endogenous circadian processes. These models are also frequently applied by defence and industrial sectors to support system safety as part of broader fatigue management strategies. FIPS is the first open-source BMM framework enabling practitioners to inspect, validate, and ideally extend BMMs.

Critical Model Information

Critical functions, arguments and outputs for each model are summarised in table below:

Model Three Process Unified
FIPS_Simulate argument "TPM" "unified"
Parameter vector function TPM_make_pvec() unified_make_pvec
Default formula alertness ~ s + c + u fatigue ~ s + I(κappa) * c
Time varying parameter names s, c, u, w s, l, c, w
Default prediction outputs KSS, alertness Fatigue (PVT lapses)

Hourly Risk Index

The FIPS package is in the process of integrating a novel model, the Hourly Risk Index (HRI), which is currently under pre-alpha testing. This model, developed on the foundation of earlier work by Folkard and Lombardi (2004), Folkard et al. (2006, 2007), and others, offers an estimation of the relative risk of safety incidents tied to different work schedules (Fischer et al., 2017). The HRI improves upon the original Risk Index model by incorporating an hourly detail level, enhancing both its predictive accuracy and application range for risk evaluation and accident analysis (UK Rail Safety and Standards Board, 2015).

While the HRI's implementation is in progress, it is not yet automated to the same standard as other models within FIPS. However, the development team is actively working to optimize and integrate the HRI fully.

The HRI pre-alpha implementation can be found on the HRI-implementation branch. The files under the R directory are under active development. A working implementation of the code can be found in https://github.com/humanfactors/FIPS/blob/HRI-implementation/notes/HRI.R in the HRI-implementation branch.

More about the HRI can be found in Roets and Folkard (2022): https://www.sciencedirect.com/science/article/abs/pii/S0925753522000972 , and Roets and Folkard (2023):  Assessing Railway Traffic Controller Safety with an Hourly Risk Index (taylorfrancis.com).

Contributing and Support

We welcome contributions great or small from the community. It would incredibly useful to receive feedback via Github Issues for anything regarding the package, including: installation issues, bugs or unexpected behaviour, usability, feature requests or inquiries, or even something you don't understand in the tutorials about this class of models more generally. Please file a Github issue for any general support queries too.

Terms for Academic Usage

In addition to the rights stipulated in the GNU Affero GPL-3, we request that all academic work leveraging FIPS provide a direct citation to the software package.

Wilson et al., (2020). FIPS: An R Package for Biomathematical Modelling of Human Fatigue Related Impairment. Journal of Open Source Software, 5(51), 2340, https://doi.org/10.21105/joss.02340

@article{Wilson2020,
  doi = {10.21105/joss.02340},
  url = {https://doi.org/10.21105/joss.02340},
  year = {2020},
  publisher = {The Open Journal},
  volume = {5},
  number = {51},
  pages = {2340},
  author = {Micah K. Wilson and Luke Strickland and Timothy Ballard},
  title = {FIPS: An R Package for Biomathematical Modelling of Human Fatigue Related Impairment},
  journal = {Journal of Open Source Software}
}

fips's People

Contributors

humanfactors avatar labarba avatar lukestrickland avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

fips's Issues

Simplify README

The current README has a lot to be desired for new users. It is admittedly pretty overwhelming looking at the front page. There are few core issues to be addressed:

1. The "Simple Use Case" section should be an actual simple use case. While I think the information there is valuable and perhaps could be in a vignette, or perhaps a separate online web documentation, there is really no need to know about the full class information on our frontpage README.

  • Move all discussion of classes to a suitable location
  • Make data objects self-contained and load with package (if they are that critical)
  • Switch to a sleep-wake binary vector as input, to avoid need for all the additional arguments in parse_sleeptimes
  • Remove all discussion of object types, and have it divided into 2 clear steps: parse_sleeptimes, FIPS_simulate.

2. It is not clearly stated anywhere what the output columns from each model's FIPS_simulation is.

  • We should have a simple table that says what the core time-varying predictions/parameter outputs are (i.e., c, s, etc...). This will be crucial for when we develop the formula interface for users to specify this themselves.

3. I think it's fine to briefly mention the two data types supported, but let's move all information about these somewhere specific where we can give the required room and formatting to get these all together.

  • Have a seperate webpage/source of information for understanding data types.

4. This is a more tentative suggestion, but I'm thinking we don't really need the "What are BMMs" up front either. We could summarise this in a simple sentence, and again direct the user to our papers or an appropriate website page for more information.

[Discussion/Notes] Provide Formula Interface

I've been doing some work on providing a simple formula interface to FIPS https://github.com/humanfactors/FIPS/tree/formula-proposal-interface. The logic of providing this interface is twofold:

  1. Users can more readily adjust what the predicted latent variable is from the outset of model simulation (e.g. provided below);
  2. It is more transparent to the users how our latent pred_vars are calculated, and what variable they should index

The prototype I've hacked together is far from complete or perfect. Currently the general interface is something like the following:

TPM.simulation.results = FIPS_simulate(
  FIPS_df = simulated.dataframe, # The FIPS_df
  modeltype = "TPM",         # three process model
  pvec = TPM_make_pvec(),      # parameter vector
  formula = alertness_with_w ~ s + c + u + w
  )

Like any big change I do want to minimize issues with legacy code. I envision that this formula argument will be optional, with the previous defaults being placed in when the user supplies no argument (that is how it currently works). However, in writing the basic logic for this feature, I have come across a few issues:

  • Currently, the FIPS_Simulation class is assigned after the main loop of each of the models
    dat <- FIPS_simulation(dat, modeltype = "TPM", pvec = pvec, pred_stat = "alertness", pred_cols = TPM_cols)
    The issue with this approach is that attributes need to be continuously added to the object within the FIPS_Simulate function. This creates a lot of noise, and you end up changing object attributes in helper functions down the line:
    add_formula_vector <- function(.FIPS_sim, pred_vector, pred_name) {
    .FIPS_sim[,pred_name] = pred_vector
    attr(.FIPS_sim, "pred_cols") = c(attr(.FIPS_sim, "pred_cols"), pred_name)
    return(.FIPS_sim)
    }
  • Ideally, we are setting all attributes like pred_stat at the time we create the object.
  • What I'm thinking is that the main loops for the model functions should effectively do nothing but be similar to a model.frame whereby it returns only the essential elements for the model.
  • We then will need constructor functions for each model type (e.g., FIPS_simulate_TPM) and these are called in the FIPS_simulate function. These functions will take in the arguments like formula all the data etc., and then produce the required object. The added benefit is that we simplify the role of the main loops.
  • This will have side-effects for the plotting functions which will need to be examined, and likely also for validation.
  • The only issue I have is how we might add in help for the formula, given it's model depdendent.

In any case, this is my notes from late on a Friday, so when I get round to implementing this Monday I can remember what the hell I was thinking!!! @lukestrickland

[BUG] Custom column names not supported

Bug description and expected behaviour

Non-standard column names for parse_sleeptimes results in error.

  • Reproduce
  • Add test for this case
CMDR_FIPS_Times = FIPS::parse_sleeptimes(
  sleeptimes = CMDR_MINIMAL,
  series.start = LAUNCH_DATE,
  series.end = END_DATE,
  roundvalue = 5,
  sleep.start.col = "sleep_start", # Nonstandard
  sleep.end.col = "sleep_end", # Nonstandard
  sleep.id.col = "Rest.Period" # Nonstandard
Error in seq.POSIXt(simulationstart, firstsleep - lubridate::minutes(expand_by),  : 
  'to' must be a "POSIXt" object
In addition: Warning messages:
1: In min(rounded.sleeptimes[[sleep.start.col]]) :
  no non-missing arguments to min; returning Inf
2: In max(rounded.sleeptimes[[sleep.end.col]]) :
 
 Error in seq.POSIXt(simulationstart, firstsleep - lubridate::minutes(expand_by),  : 
  'to' must be a "POSIXt" object 
8.
stop("'to' must be a \"POSIXt\" object") 
7.
seq.POSIXt(simulationstart, firstsleep - lubridate::minutes(expand_by), 
    by = emins) 
6.
seq(simulationstart, firstsleep - lubridate::minutes(expand_by), 
    by = emins) 
5.
eval_tidy(xs[[j]], mask) 
4.
tibble_quos(xs[!is.null], .rows, .name_repair) 
3.
tibble::tibble(datetime = seq(simulationstart, firstsleep - lubridate::minutes(expand_by), 
    by = emins), sleep.id = NA, wake_status = T) at data_sleeptimesformat.R#134
2.
generate_presleep_times(series.start, minimum.sleepstart, roundvalue) at data_sleeptimesformat.R#96
1.
FIPS::parse_sleeptimes(sleeptimes = CMDR_MINIMAL, series.start = LAUNCH_DATE, 
    series.end = END_DATE, roundvalue = 5, sleep.start.col = "sleep_start", 
    sleep.end.col = "sleep_end", sleep.id.col = "Rest.Period") 

parse_sleeptimes - roundvalue must be a whole number

I wanted to use a small roundvalue to check an integral against a numerical approximation. I tried to set roundvalue to a decimal, e.g.,0.5 to get predictions every 30 seconds, but I encountered an error. I also get an error for decimal roundvalues bigger than 1 (e.g., roundvalue=2.5)

I think at least we should have an error message explaining that roundvalue must be a whole number.

library(FIPS)
library(tidyverse)
# Simulation start date time (i.e., when you want first predictions to begin)
simulation.start = lubridate::ymd_hms('2018-05-01 00:00:00', tz = "Australia/Perth")
# Simulation end date time (i.e., when you want predictions to end)
simulation.end = lubridate::ymd_hms('2018-05-09 21:00:00', tz = "Australia/Perth")
# Sleep times, 5 hours per night, starting 23:00
example.sleeptimes <- tibble::tibble(
  sleep.start = seq(
    from = lubridate::ymd_hms('2018-05-01 02:00:00', tz = "Australia/Perth"),
    to = lubridate::ymd_hms('2018-05-09 16:00:00', tz = "Australia/Perth"),
    by = '24 hours'),
  sleep.end = sleep.start + lubridate::dhours(3),
  sleep.id = rank(sleep.start))

simulated.dataframe = parse_sleeptimes(
  sleeptimes = example.sleeptimes,
  series.start = simulation.start,
  series.end = simulation.end,
  sleep.start.col = "sleep.start",
  sleep.end.col = "sleep.end",
  sleep.id.col = "sleep.id",
  roundvalue = 0.5)

System Information

sessionInfo()
R version 3.6.2 (2019-12-12)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 10 x64 (build 18363)

Matrix products: default

locale:
[1] LC_COLLATE=English_Australia.1252  LC_CTYPE=English_Australia.1252   
[3] LC_MONETARY=English_Australia.1252 LC_NUMERIC=C                      
[5] LC_TIME=English_Australia.1252    

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] forcats_0.5.0   stringr_1.4.0   dplyr_1.0.2     purrr_0.3.4     readr_1.3.1    
 [6] tidyr_1.1.2     tibble_3.0.3    ggplot2_3.3.2   tidyverse_1.3.0 FIPS_0.1.1     

loaded via a namespace (and not attached):
 [1] tidyselect_1.1.0 haven_2.2.0      lattice_0.20-38  colorspace_1.4-1
 [5] vctrs_0.3.4      generics_0.0.2   utf8_1.1.4       rlang_0.4.7     
 [9] pillar_1.4.6     glue_1.4.2       withr_2.3.0      DBI_1.1.0       
[13] dbplyr_1.4.3     modelr_0.1.7     readxl_1.3.1     lifecycle_0.2.0 
[17] munsell_0.5.0    gtable_0.3.0     cellranger_1.1.0 rvest_0.3.5     
[21] labeling_0.3     fansi_0.4.1      broom_0.5.6      Rcpp_1.0.5      
[25] backports_1.1.10 scales_1.1.1     checkmate_2.0.0  jsonlite_1.6.1  
[29] farver_2.0.3     fs_1.4.1         hms_0.5.3        digest_0.6.25   
[33] stringi_1.4.6    grid_3.6.2       cli_2.0.2        tools_3.6.2     
[37] magrittr_1.5     crayon_1.3.4     pkgconfig_2.0.3  ellipsis_0.3.1  
[41] xml2_1.2.2       reprex_0.3.0     lubridate_1.7.9  assertthat_0.2.1
[45] httr_1.4.1       rstudioapi_0.11  R6_2.4.1         nlme_3.1-142    
[49] compiler_3.6.2  

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.