APTExperiment¶
This class stores all necessary information for an experimental data set that you want to fit.
At a minimum, APTExperiment requires:
- Initial conditions for all states (unknown initial conditions can be set to a parameter).
- Some state data for fitting purposes.
Note
While initial conditions are required, tsim for the ODE is not required. APTexperiment will automatically generate the relevant list of times to solve the ODE based on your data. See in-gettime on obtaining this autogenerated list.
Advanced support includes:
- Fitting a time shift when data is relative to some time after the onset of your system. This may be relevant for hospital data, where records begin relative to hospital enrollment rather than disease enrollment.
- Experiments with infusions (bolus, ramp, zero-order-hold, or any combination thereof). Infusion magnitudes, duration, and times must be known and cannot currently be fit. However, infusions may be used in combination with a timeshift (see above point) as long as infusion times are relative to the same time as your data. Sinusoidal infusions will NOT supported.
Major Limitations:
- Data must describe a state directly. APTexperiment currently does a 1:1 comparison of data against its relevant state. Mathematically, in state-space form, C must be the identity matrix.
Initializing an experiment¶
apt.experiment(name)
Initialize an APTexperiment object. Required.
Args:
- name (str): Name of your experiment. Alphanumerical characters only! ‘_’ is allowed. All other special characters including spaces are not allowed.
Returns:
- APTexperiment object. This object will contain all information about your experiment and will store data, initial conditions, and infusions if applicable.
Raises:
- NameError about experiment names being alphanumerics + _ only.
Example:
experiment1 = apt.experiment('Dataset_1')
Adding data to the experiment¶
apt.experiment.add_data(data)
Deep copies an APTdata object into APTexperiment. The APTdata object may be reused later on. See Tutorial or APTdata documentation for more information. This function can be run as many times as needed.
Note
Data will be overwritten if applicable! Suppose data for state s at time tn is already loaded into apt.experiment: s(tn). If you load in an APTdata object that contains a value at s(tn), a warning message will be shown, but s(tn) will be overwritten. Ensure this is correct before proceeding.
Args:
- data (APTdata object): An object containing data at various timepoints and states for your model.
Example:
experiment1.add_data(data_1) experiment1.add_data(data_1_initialconditions)
Fitting Initial Conditions¶
apt.experiment.fitInitialCondition(dict)
If data for an initial condition is unavailable, then it must be set to a parameter. The user provides a dictionary of key-pair: {states (str) : parameter (str)} to let the model know which parameters should be used to fit which states.
Args:
- dict (dictionary): A dictionary of key-pair: {states (str) : parameter (str)}. Ensure the parameter is defined in apt!
Example:
model = apt.aptmodel() model.add_states('Ca','Cb','Cc','Cd') model.add_par('Ca_initial', 0, 5) model.add_par('Cb_initial', 0, 5) experiment1 = apt.experiment('Dataset_1') experiment1.add_data(Cc_data) experiment1.add_data(Cd_data) experiment1.fitInitialCondition({'Ca':'Ca_initial', 'Cb':'Cb_initial'})
apt.exeriment.set_tshift_par(parname)
Fit a time shift to the model using a parameter. This parameter will shift all data to the right if positive and shift all data to the left if negative. For example, a time shift parameter of 5 means data at t=0 will now be t=5. A typical use case would be hospital data which is relative to enrollment time rather than disease time zero.
Args:
- parname (str): The name of the parameter used for the time shift. Ensure the parameter is defined in apt!
Example:
model = apt.aptmodel() model.add_states('Ca') model.add_par('tshift',0, 10) # allow a shift between 0-10 hours experiment1 = apt.experiment('Dataset_1') experiment1.add_data(dataset1) experiment1.set_tshift_par('tshift')
Adding infusion information¶
apt.experiment.add_infusion(zoh=zoh_array, ramp=ramp_array, bolus=bolus_array)
Define the infusions that generated this experiment. Providing inputs for all 3 types of infusions are not necessary; simply insert the ones that are necessary to your experiment. The infusion information will be ignored unless APTmodel is set to use infusions!
Args:
- zoh_array (array-like): array defining the values of a zero-order-hold infusion. See Infusion Input Requirements.
Note
- Zero-order-hold: Holds the infusion at the last defined value until the next timepoint of the array is reached.
- Ramp: Adds an infusion that was linearly interpolated between the relevant ramp values of the current time.
- Bolus: Pauses integration and adds the infusion value directly to the states of the ODE.
Infusion Input Requirements¶
Zero-order-hold and ramp infusion arrays be of a specific format.
- They should be provided as an array-like object. A NumPy array is highly recommended.
- The first column must be a column of times describing infusion times. Times MUST be monotonically increasing.
- The other columns describe a separate infusion: u[0], u[1], … u[n]
- The first row is required to be the start-time of your simulation.
- The last row is required to be the end-time of your simulation. Values on this row are ignored in the zero-order-hold case.
- The zero-order-hold infusion array and the ramp infusion array MUST have the same number of columns. The column order is assumed to be the same for both arrays.
| time | u[0] | u[1] | … | u[n] |
|---|---|---|---|---|
| tstart | 5 | 0 | … | 1 |
| 3 | 0 | 4 | … | 0 |
| tend | 0 | 0 | … | 0 |
Example:
# Ramp u[0] from (0,0) to (4,4) then shut off.
model = apt.aptmodel()
model.add_states('Ca','Cb')
infus_ramp = np.zeros([3,3])
infus_ramp[0] = [0,0,0]
infus_ramp[1] = [4,4,0]
infus_ramp[2] = [10,4,0]
infus_zoh = np.zeros([3,3])
infus_zoh[0] = [0,0,0]
infus_zoh[1] = [4,-4,3]
infus_zoh[2] = [10,-4,0]
experiment1 = apt.experiment('Dataset_1')
experiment1.add_data(dataset1)
experiment1.add_infusion(zoh=infus_zoh, ramp=infus_ramp)
The bolus infusion array must be of the following format.
- It should be provided as an array-like object. A NumPy array is highly recommended.
- The first column must be a column of times describing infusion times. Times MUST be monotonically increasing.
- A other columns must pertain to each state in the model, in the order that was provided into APTmodel.
- There should not be a bolus at the start-time!
Example:
model = apt.aptmodel()
model.add_states('Ca','Cb','Cc','Cd')
| time | Ca | Cb | Cc | Cd |
|---|---|---|---|---|
| bol t1 | 5 | 0 | 0 | 1 |
| bol t2 | 0 | 4 | 0 | 0 |
| bol t3 | 0 | 0 | 1 | 4 |
infus_bol = np.zeros([3,4])
infus_bol[0] = [5,0,0,1]
infus_bol[1] = [0,4,0,0]
infus_bol[2] = [0,0,1,4]
experiment1 = apt.experiment('Dataset_1')
experiment1.add_data(dataset1)
experiment1.add_infusion(bolus=infus_bol)
Verifying the Experiment¶
apt.experiment.get_time()
Returns the autogenerated list of times for the experiment based on the loaded data.
Returns:
- NumPy array of times
apt.experiment.show(showall)
Prints the data and infusions, if applicable, currently loaded into the experiment.
Args:
- showall (bool) optional: By default, show() will truncate the data and print only the first and last few lines of the data. Setting showall to be true will display all the data.
Example:
experiment1 = apt.experiment('Dataset_1')
experiment1.add_data(dataset1)
print(experiment1.get_time())
experiment1.show(showall=True)