def get_available_label_stores(self, usefield='tryall'):
        """
        Get the label store values that may be used
        for writing this annotation.

        Available store values include:
        - the undefined values in the standard wfdb labels
        - the store values not used in the current
          annotation object.
        - the store values whose standard wfdb symbols/descriptions
          match those of the custom labels (if custom_labels exists)

        If 'usefield' is explicitly specified, the function will use that
        field to figure out available label stores. If 'usefield'
        is set to 'tryall', the function will choose one of the contained
        attributes by checking availability in the order: label_store, symbol, description
        """


        # Figure out which field to use to get available labels stores.
        if usefield == 'tryall':
            if self.label_store is not None:
                usefield = 'label_store'
            elif self.symbol is not None:
                usefield = 'symbol'
            elif self.description is not None:
                usefield = 'description'
            else:
                raise ValueError('No label fields are defined. At least one of the following is required: ', ann_label_fields)
            return self.get_available_label_stores(usefield = usefield)
        # Use the explicitly stated field to get available stores.
        else:
            # If usefield == 'label_store', there are slightly fewer/different steps
            # compared to if it were another option

            contained_field = getattr(self, usefield)

            # Get the unused label_store values
            if usefield == 'label_store':
                unused_label_stores = set(ann_label_table['label_store'].values) - contained_field
            else:
                # the label_store values from the standard wfdb annotation labels
                # whose symbols are not contained in this annotation
                unused_field = set(ann_label_table[usefield].values) - contained_field
                unused_label_stores = ann_label_table.loc[ann_label_table[usefield] in unused_field, 'label_store'].values

            # Get the standard wfdb label_store values overwritten by the
            # custom_labels if any
            if self.custom_symbols is not None:
                custom_field = set(self.get_custom_label_attribute(usefield))
                if usefield == 'label_store':
                    overwritten_label_stores = set(custom_field).intersection(set(ann_label_table['label_store']))
                else:
                    overwritten_fields = set(custom_field).intersection(set(ann_label_table[usefield]))
                    overwritten_label_stores = ann_label_table.loc[ann_label_table[usefield] in overwritten_fields, 'label_store'].values
            else:
                overwritten_label_stores = set()


            # The undefined values in the standard wfdb labels
            undefined_label_stores = self.get_undefined_label_stores()
            # Final available label stores = undefined + unused + overwritten
            available_label_stores = set(undefined_label_stores).union(set(unused_label_stores)).union(overwritten_label_stores)

            return available_label_stores
Get the label store values that may be used
        for writing this annotation.

        Available store values include:
        - the undefined values in the standard wfdb labels
        - the store values not used in the current
          annotation object.
        - the store values whose standard wfdb symbols/descriptions
          match those of the custom labels (if custom_labels exists)

        If 'usefield' is explicitly specified, the function will use that
        field to figure out available label stores. If 'usefield'
        is set to 'tryall', the function will choose one of the contained
        attributes by checking availability in the order: label_store, symbol, description