//  [python]
def _scale_back(self, update_heap_pointers=True):
        """
        Update the parent array, using the (latest) scaled array.

        If ``update_heap_pointers`` is `False`, this will leave all the heap
        pointers in P/Q columns as they are verbatim--it only makes sense to do
        this if there is already data on the heap and it can be guaranteed that
        that data has not been modified, and there is not new data to add to
        the heap.  Currently this is only used as an optimization for
        CompImageHDU that does its own handling of the heap.
        """
        # Running total for the new heap size
        heapsize = 0

        for indx, name in enumerate(self.dtype.names):
            column = self._coldefs[indx]
            recformat = column.format.recformat
            raw_field = _get_recarray_field(self, indx)

            # add the location offset of the heap area for each
            # variable length column
            if isinstance(recformat, _FormatP):
                # Irritatingly, this can return a different dtype than just
                # doing np.dtype(recformat.dtype); but this returns the results
                # that we want.  For example if recformat.dtype is 'S' we want
                # an array of characters.
                dtype = np.array([], dtype=recformat.dtype).dtype

                if update_heap_pointers and name in self._converted:
                    # The VLA has potentially been updated, so we need to
                    # update the array descriptors
                    raw_field[:] = 0  # reset
                    npts = [np.prod(arr.shape) for arr in self._converted[name]]

                    raw_field[: len(npts), 0] = npts
                    raw_field[1:, 1] = (
                        np.add.accumulate(raw_field[:-1, 0]) * dtype.itemsize
                    )
                    raw_field[:, 1][:] += heapsize

                heapsize += raw_field[:, 0].sum() * dtype.itemsize
                # Even if this VLA has not been read or updated, we need to
                # include the size of its constituent arrays in the heap size
                # total
                if type(recformat) == _FormatP and heapsize >= 2**31:
                    raise ValueError(
                        "The heapsize limit for 'P' format has been reached. "
                        "Please consider using the 'Q' format for your file."
                    )
            if isinstance(recformat, _FormatX) and name in self._converted:
                _wrapx(self._converted[name], raw_field, recformat.repeat)
                continue

            scale_factors = self._get_scale_factors(column)
            _str, _bool, _number, _scale, _zero, bscale, bzero, _ = scale_factors

            field = self._converted.get(name, raw_field)

            # conversion for both ASCII and binary tables
            if _number or _str:
                if _number and (_scale or _zero) and column._physical_values:
                    dummy = field.copy()
                    if _zero:
                        # Cast before subtracting to avoid overflow problems.
                        dummy -= np.array(bzero).astype(dummy.dtype, casting="unsafe")
                    if _scale:
                        dummy /= bscale
                    # This will set the raw values in the recarray back to
                    # their non-physical storage values, so the column should
                    # be mark is not scaled
                    column._physical_values = False
                elif _str or isinstance(self._coldefs, _AsciiColDefs):
                    dummy = field
                else:
                    continue

                # ASCII table, convert numbers to strings
                if isinstance(self._coldefs, _AsciiColDefs):
                    self._scale_back_ascii(indx, dummy, raw_field)
                # binary table string column
                elif isinstance(raw_field, chararray.chararray):
                    self._scale_back_strings(indx, dummy, raw_field)
                # all other binary table columns
                else:
                    if len(raw_field) and isinstance(raw_field[0], np.integer):
                        dummy = np.around(dummy)

                    if raw_field.shape == dummy.shape:
                        raw_field[:] = dummy
                    else:
                        # Reshaping the data is necessary in cases where the
                        # TDIMn keyword was used to shape a column's entries
                        # into arrays
                        raw_field[:] = dummy.ravel().view(raw_field.dtype)

                del dummy

            # ASCII table does not have Boolean type
            elif _bool and name in self._converted:
                choices = (
                    np.array([ord("F")], dtype=np.int8)[0],
                    np.array([ord("T")], dtype=np.int8)[0],
                )
                raw_field[:] = np.choose(field, choices)

        # Store the updated heapsize
        self._heapsize = heapsize