Using Consumables - UCL/TLOmodel GitHub Wiki
- Consumables are used in the provision of a service in the healthcare system (e.g. medicines and other necessary materials).
- Consumables are referred to with a unique item_code.
- A 'request' for consumables is made during a during an HSIevent and can be for one or many items at once.
There are a number of steps to using Consumables, described in turn below.
There are two helper function that can assist in finding them item_code you need.
This will return the int that is the item_code for that item.
e.g.
item_code = sim.modules['HealthSystem'].get_item_code_from_item_name("Tenofovir (TDF)/Emtricitabine (FTC), tablet, 300/200 mg")This will return a dict of the form {<item_code>: <quantity>} that corresponds to that package.
e.g.
item_code = sim.modules['HealthSystem'].get_item_codes_from_package_name("HIV Testing Services")It is best to store all the item_codes in a convenient structure (e.g. a dict) and to create a method on the disease module called find_cons_item_codes or similar, which contains the routines needed to populate that structure. This can be called at initialise_simulation(). The requests for consumables in the HSI can then refer to that structure.
A common format for the method on the module would be:
# ... within the module:
def get_item_code(self) --> dict:
   _get_item_code = self.sim.modules['HealthSystem'].get_item_codes_from_package_name
   _codes = dict()
   _codes['treatment_A'] = _get_item_code("item_name_for_treatment_A")
   _codes['treatment_B'] = [_get_item_code("item_name_for_treatment_B")] + [_get_item_code("item_name_something_else")]
   _codes['treatment_C'] = _get_item_code("item_name_for_treatment_C")
   return _codesDo:
- Group all the requests in one place: e.g. factorise the looking-up of the item_codes into a method and call it atinitialise_simulation.
- Use the helper functions in HealthSystem:get_item_code_from_item_nameandget_item_codes_from_package_name
Do not:
- Look-up the item_code at run-time in the HSI (this will cause the look-up to happen every time the HSI is created, which could be a lot!)
- Scatter looking up of consumables throughout the code.
- Look-up the codes manually using the internal data of the HealthSystemmodule.
All request for consumables are done using get_consumables, which is a method on the HSI_Event base-class. So, within an HSI it's accessed with self.get_consumables(...). It's signature is:
    def get_consumables(self,
                        item_codes: Optional[Union[np.integer, int, list, set, dict]] = None,
                        optional_item_codes: Optional[Union[np.integer, int, list, set, dict]] = None,
                        to_log: Optional[bool] = True,
                        return_individual_results: Optional[bool] = False
                        ) -> Union[bool, dict]:Note that:
- 
The argument item_codes[andoptional_item_codes] can be provided as:- an int, representing the singleitem_coderequested (and for which a quantity of 1 is assumed);
- a listorset, representing the collection ofitem_codes that are needed (for each of a which a quantity of 1 is assumed);
- a dictof the form{<item_code>: <quantity>}, in which the quantity of eachitem_codeis specified;
 
- an 
- 
The item optional_item_codesis optional and can be used to specify items that should be requested (and logged) but which should not affect the summary result for availability/non-availability of all the items requested. This is useful when a large set of items may be used, but the viability of a subsequent operation depends only on a subset.
- 
The argument to_logdetermines if the request (whatever its outcome) is logged (to['tlo.methods.healthsystem']['Consumables']). The defaults toTruebut can over-ridden (e.g. to query availability only).
- 
The method return either a bool[default] (indicating that all the (non-optional) items (initem_codes) requested are available), or adict(indicating the availability of each requesteditem_codesandoptional_item_codes).- The default is always to return the summary result (a bool) but this can be over-ridden with the argumentreturn_individual_results=True.
 
- The default is always to return the summary result (a 
N.B. If the a consumable is not available then the HSI must not represent it having an effect. Instead, the effect of an alternative treatment or not treatment must be represented.
Examples:
if self.get_consumables(self.module.cons_codes['treatment_A']):
   # do the treatment
else:
   # determine the outcome if there is no treatment# Construct request for ten of each item_code used in treatment_B
cons = {_i: 10 for _i in self.module.cons_codes['treatment_B']}
# Check availability (getting individual results)
avail = self.get_consumables(cons, return_individual_results=True)Notes:
- Use the same formats for item_code, when specifying the consumable requirement of aDxTest.
At any point from initialise_simulation onwards, the probability with which an item is available can be edited using this helper function on the HealthSystem module.
    def override_availability_of_consumables(self, item_codes) -> None:
         """Over-ride the availability (for all months and all facilities) of certain consumables item_codes.
         :param item_codes: Dictionary of the form {<item_code>: probability_that_item_is_available}
         :return: None
         """For example:
self.sim.modules['HealthSystem'].override_availability_of_consumables({item_code: updated_probability_of_being_available.})
Note that this will affect the availability of that consumable at all facilities and for the rest of the simulation (unless the value is over-ridden again).
The following options (passed to the HealthSystem) are relevant:
- 
cons_availability: This can benone(no consumable is available)all(all consumables are available) ordefault[default] (consumables are available according to a probability specified in a the relevantResourceFile).
- 
disable: In this mode, all consumables are considered to be available but there is no logging.