export *MDF* to other formats. The *MDF* file name is used is
        available, else the *filename* argument must be provided.

        The *pandas* export option was removed. you should use the method
        *to_dataframe* instead.

        Parameters
        ----------
        fmt : string
            can be one of the following:

            * `csv` : CSV export that uses the ";" delimiter. This option
              will generate a new csv file for each data group
              (<MDFNAME>_DataGroup_<cntr>.csv)

            * `hdf5` : HDF5 file output; each *MDF* data group is mapped to
              a *HDF5* group with the name 'DataGroup_<cntr>'
              (where <cntr> is the index)

            * `excel` : Excel file output (very slow). This option will
              generate a new excel file for each data group
              (<MDFNAME>_DataGroup_<cntr>.xlsx)

            * `mat` : Matlab .mat version 4, 5 or 7.3 export. If
              *single_time_base==False* the channels will be renamed in the mat
              file to 'D<cntr>_<channel name>'. The channel group
              master will be renamed to 'DM<cntr>_<channel name>'
              ( *<cntr>* is the data group index starting from 0)

            * `parquet` : export to Apache parquet format

        filename : string | pathlib.Path
            export file name

        **kwargs

            * `single_time_base`: resample all channels to common time base,
              default *False*
            * `raster`: float time raster for resampling. Valid if
              *single_time_base* is *True*
            * `time_from_zero`: adjust time channel to start from 0
            * `use_display_names`: use display name instead of standard channel
              name, if available.
            * `empty_channels`: behaviour for channels without samples; the
              options are *skip* or *zeros*; default is *skip*
            * `format`: only valid for *mat* export; can be '4', '5' or '7.3',
              default is '5'
            * `oned_as`: only valid for *mat* export; can be 'row' or 'column'
            * `keep_arrays` : keep arrays and structure channels as well as the
              component channels. If *True* this can be very slow. If *False*
              only the component channels are saved, and their names will be
              prefixed with the parent channel.
            * reduce_memory_usage : bool
              reduce memory usage by converting all float columns to float32 and
              searching for minimum dtype that can reprezent the values found
              in integer columns; default *False*
            * compression : str
              compression to be used

              * for ``parquet`` : "GZIP" or "SANPPY"
              * for ``hfd5`` : "gzip", "lzf" or "szip"
              * for ``mat`` : bool

def export(self, fmt, filename=None, **kargs):
        """ export *MDF* to other formats. The *MDF* file name is used is
        available, else the *filename* argument must be provided.

        The *pandas* export option was removed. you should use the method
        *to_dataframe* instead.

        Parameters
        ----------
        fmt : string
            can be one of the following:

            * `csv` : CSV export that uses the ";" delimiter. This option
              will generate a new csv file for each data group
              (<MDFNAME>_DataGroup_<cntr>.csv)

            * `hdf5` : HDF5 file output; each *MDF* data group is mapped to
              a *HDF5* group with the name 'DataGroup_<cntr>'
              (where <cntr> is the index)

            * `excel` : Excel file output (very slow). This option will
              generate a new excel file for each data group
              (<MDFNAME>_DataGroup_<cntr>.xlsx)

            * `mat` : Matlab .mat version 4, 5 or 7.3 export. If
              *single_time_base==False* the channels will be renamed in the mat
              file to 'D<cntr>_<channel name>'. The channel group
              master will be renamed to 'DM<cntr>_<channel name>'
              ( *<cntr>* is the data group index starting from 0)

            * `parquet` : export to Apache parquet format

        filename : string | pathlib.Path
            export file name

        **kwargs

            * `single_time_base`: resample all channels to common time base,
              default *False*
            * `raster`: float time raster for resampling. Valid if
              *single_time_base* is *True*
            * `time_from_zero`: adjust time channel to start from 0
            * `use_display_names`: use display name instead of standard channel
              name, if available.
            * `empty_channels`: behaviour for channels without samples; the
              options are *skip* or *zeros*; default is *skip*
            * `format`: only valid for *mat* export; can be '4', '5' or '7.3',
              default is '5'
            * `oned_as`: only valid for *mat* export; can be 'row' or 'column'
            * `keep_arrays` : keep arrays and structure channels as well as the
              component channels. If *True* this can be very slow. If *False*
              only the component channels are saved, and their names will be
              prefixed with the parent channel.
            * reduce_memory_usage : bool
              reduce memory usage by converting all float columns to float32 and
              searching for minimum dtype that can reprezent the values found
              in integer columns; default *False*
            * compression : str
              compression to be used

              * for ``parquet`` : "GZIP" or "SANPPY"
              * for ``hfd5`` : "gzip", "lzf" or "szip"
              * for ``mat`` : bool

        """

        from time import perf_counter as pc

        header_items = ("date", "time", "author", "department", "project", "subject")

        if fmt != "pandas" and filename is None and self.name is None:
            message = (
                "Must specify filename for export"
                "if MDF was created without a file name"
            )
            logger.warning(message)
            return

        single_time_base = kargs.get("single_time_base", False)
        raster = kargs.get("raster", 0)
        time_from_zero = kargs.get("time_from_zero", True)
        use_display_names = kargs.get("use_display_names", True)
        empty_channels = kargs.get("empty_channels", "skip")
        format = kargs.get("format", "5")
        oned_as = kargs.get("oned_as", "row")
        reduce_memory_usage = kargs.get("reduce_memory_usage", False)
        compression = kargs.get("compression", "")

        if compression == 'SNAPPY':
            try:
                import snappy
            except ImportError:
                logger.warning(
                    "snappy compressor is not installed; compression will be set to GZIP"
                )
                compression = "GZIP"

        name = Path(filename) if filename else self.name

        if fmt == "parquet":
            try:
                from fastparquet import write as write_parquet
            except ImportError:
                logger.warning(
                    "fastparquet not found; export to parquet is unavailable"
                )
                return

        elif fmt == "hdf5":
            try:
                from h5py import File as HDF5
            except ImportError:
                logger.warning("h5py not found; export to HDF5 is unavailable")
                return

        elif fmt == "excel":
            try:
                import xlsxwriter
            except ImportError:
                logger.warning("xlsxwriter not found; export to Excel unavailable")
                return

        elif fmt == "mat":
            if format == "7.3":
                try:
                    from hdf5storage import savemat
                except ImportError:
                    logger.warning(
                        "hdf5storage not found; export to mat v7.3 is unavailable"
                    )
                    return
            else:
                try:
                    from scipy.io import savemat
                except ImportError:
                    logger.warning("scipy not found; export to mat is unavailable")
                    return

        if single_time_base or fmt == "parquet":
            df = self.to_dataframe(
                raster=raster,
                time_from_zero=time_from_zero,
                use_display_names=use_display_names,
                empty_channels=empty_channels,
                reduce_memory_usage=reduce_memory_usage,
            )
            units = OrderedDict()
            comments = OrderedDict()
            used_names = UniqueDB()

            for i, grp in enumerate(self.groups):
                if self._terminate:
                    return

                included_channels = self._included_channels(i)

                for j in included_channels:
                    ch = grp.channels[j]

                    if use_display_names:
                        channel_name = ch.display_name or ch.name
                    else:
                        channel_name = ch.name

                    channel_name = used_names.get_unique_name(channel_name)

                    if hasattr(ch, 'unit'):
                        unit = ch.unit
                        if ch.conversion:
                            unit = unit or ch.conversion.unit
                    comment = ch.comment

                    units[channel_name] = unit
                    comments[channel_name] = comment

        if fmt == "hdf5":
            name = name.with_suffix(".hdf")

            if single_time_base:
                with HDF5(str(name), "w") as hdf:
                    # header information
                    group = hdf.create_group(str(name))

                    if self.version in MDF2_VERSIONS + MDF3_VERSIONS:
                        for item in header_items:
                            group.attrs[item] = self.header[item]

                    # save each data group in a HDF5 group called
                    # "DataGroup_<cntr>" with the index starting from 1
                    # each HDF5 group will have a string attribute "master"
                    # that will hold the name of the master channel

                    for channel in df:
                        samples = df[channel]
                        unit = units[channel]
                        comment = comments[channel]

                        if samples.dtype.kind == 'O':
                            continue

                        if compression:
                            dataset = group.create_dataset(
                                channel,
                                data=samples,
                                compression=compression,
                            )
                        else:
                            dataset = group.create_dataset(channel, data=samples)
                        unit = unit.replace("\0", "")
                        if unit:
                            dataset.attrs["unit"] = unit
                        comment = comment.replace("\0", "")
                        if comment:
                            dataset.attrs["comment"] = comment

            else:
                with HDF5(str(name), "w") as hdf:
                    # header information
                    group = hdf.create_group(str(name))

                    if self.version in MDF2_VERSIONS + MDF3_VERSIONS:
                        for item in header_items:
                            group.attrs[item] = self.header[item]

                    # save each data group in a HDF5 group called
                    # "DataGroup_<cntr>" with the index starting from 1
                    # each HDF5 group will have a string attribute "master"
                    # that will hold the name of the master channel
                    for i, grp in enumerate(self.groups):
                        names = UniqueDB()
                        if self._terminate:
                            return
                        group_name = r"/" + f"DataGroup_{i+1}"
                        group = hdf.create_group(group_name)

                        master_index = self.masters_db.get(i, -1)

                        if master_index:
                            group.attrs["master"] = grp.channels[master_index].name

                        channels = self.select(
                            [(ch.name, i, None) for ch in grp.channels]
                        )

                        for j, sig in enumerate(channels):
                            if use_display_names:
                                name = sig.display_name or sig.name
                            else:
                                name = sig.name
                            name = names.get_unique_name(name)
                            if reduce_memory_usage:
                                sig.samples = downcast(sig.samples)
                            if compression:
                                dataset = group.create_dataset(
                                    name,
                                    data=sig.samples,
                                    compression=compression,
                                )
                            else:
                                dataset = group.create_dataset(name, data=sig.samples, dtype=sig.samples.dtype)
                            unit = sig.unit
                            if unit:
                                dataset.attrs["unit"] = unit
                            comment = sig.comment.replace("\0", "")
                            if comment:
                                dataset.attrs["comment"] = comment

        elif fmt == "excel":

            if single_time_base:
                name = name.with_suffix(".xlsx")
                message = f'Writing excel export to file "{name}"'
                logger.info(message)

                workbook = xlsxwriter.Workbook(str(name))
                sheet = workbook.add_worksheet("Channels")

                for col, (channel_name, channel_unit) in enumerate(units.items()):
                    if self._terminate:
                        return
                    samples = df[channel_name]
                    sig_description = f"{channel_name} [{channel_unit}]"
                    sheet.write(0, col, sig_description)
                    try:
                        sheet.write_column(1, col, samples.astype(str))
                    except:
                        vals = [str(e) for e in sig.samples]
                        sheet.write_column(1, col, vals)

                workbook.close()

            else:
                while name.suffix == ".xlsx":
                    name = name.stem

                count = len(self.groups)

                for i, grp in enumerate(self.groups):
                    if self._terminate:
                        return
                    message = f"Exporting group {i+1} of {count}"
                    logger.info(message)

                    data = self._load_data(grp)

                    data = b"".join(d[0] for d in data)
                    data = (data, 0, -1)

                    master_index = self.masters_db.get(i, None)
                    if master_index is not None:
                        master = self.get(group=i, index=master_index, data=data)

                        if raster and len(master):
                            raster_ = np.arange(
                                master[0], master[-1], raster, dtype=np.float64
                            )
                            master = master.interp(raster_)
                        else:
                            raster_ = None
                    else:
                        master = None
                        raster_ = None

                    if time_from_zero:
                        master.samples -= master.samples[0]

                    group_name = f"DataGroup_{i+1}"
                    wb_name = Path(f"{name.stem}_{group_name}.xlsx")
                    workbook = xlsxwriter.Workbook(str(wb_name))

                    sheet = workbook.add_worksheet(group_name)

                    if master is not None:

                        sig_description = f"{master.name} [{master.unit}]"
                        sheet.write(0, 0, sig_description)
                        sheet.write_column(1, 0, master.samples.astype(str))

                        offset = 1
                    else:
                        offset = 0

                    for col, _ in enumerate(grp.channels):
                        if self._terminate:
                            return
                        if col == master_index:
                            offset -= 1
                            continue

                        sig = self.get(group=i, index=col, data=data)
                        if raster_ is not None:
                            sig = sig.interp(raster_, self._integer_interpolation)

                        sig_description = f"{sig.name} [{sig.unit}]"
                        sheet.write(0, col + offset, sig_description)

                        try:
                            sheet.write_column(1, col + offset, sig.samples.astype(str))
                        except:
                            vals = [str(e) for e in sig.samples]
                            sheet.write_column(1, col + offset, vals)

                    workbook.close()
                    del self._master_channel_cache[(i, 0, -1)]

        elif fmt == "csv":

            if single_time_base:
                name = name.with_suffix(".csv")
                message = f'Writing csv export to file "{name}"'
                logger.info(message)
                with open(name, "w", newline="") as csvfile:
                    writer = csv.writer(csvfile)

                    names_row = [
                        f"{channel_name} [{channel_unit}]"
                        for (channel_name, channel_unit) in units.items()
                    ]
                    writer.writerow(names_row)

                    vals = [df[name] for name in df]

                    if self._terminate:
                        return

                    for row in zip(*vals):
                        writer.writerow(row)

            else:

                name = name.with_suffix(".csv")

                count = len(self.groups)
                for i, grp in enumerate(self.groups):
                    if self._terminate:
                        return
                    message = f"Exporting group {i+1} of {count}"
                    logger.info(message)
                    data = self._load_data(grp)

                    data = b"".join(d[0] for d in data)
                    data = (data, 0, -1)

                    group_csv_name = name.parent / f"{name.stem}_DataGroup_{i+1}.csv"

                    with open(group_csv_name, "w", newline="") as csvfile:
                        writer = csv.writer(csvfile)

                        master_index = self.masters_db.get(i, None)
                        if master_index is not None:
                            master = self.get(group=i, index=master_index, data=data)

                            if raster and len(master):
                                raster_ = np.arange(
                                    master[0], master[-1], raster, dtype=np.float64
                                )
                                master = master.interp(raster_)
                            else:
                                raster_ = None
                        else:
                            master = None
                            raster_ = None

                        if time_from_zero:
                            if master is None:
                                pass
                            elif len(master):
                                master.samples -= master.samples[0]

                        ch_nr = len(grp.channels)
                        if master is None:
                            channels = [
                                self.get(group=i, index=j, data=data)
                                for j in range(ch_nr)
                            ]
                        else:
                            if raster_ is not None:
                                channels = [
                                    self.get(group=i, index=j, data=data).interp(
                                        raster_, self._integer_interpolation
                                    )
                                    for j in range(ch_nr)
                                    if j != master_index
                                ]
                            else:
                                channels = [
                                    self.get(group=i, index=j, data=data)
                                    for j in range(ch_nr)
                                    if j != master_index
                                ]

                        if raster_ is not None:
                            cycles = len(raster_)
                        else:
                            cycles = grp.channel_group["cycles_nr"]

                        if empty_channels == "zeros":
                            for channel in channels:
                                if not len(channel):
                                    channel.samples = np.zeros(
                                        cycles, dtype=channel.samples.dtype
                                    )

                        if master is not None:
                            names_row = [master.name]
                            vals = [master.samples]
                        else:
                            names_row = []
                            vals = []
                        names_row += [f"{ch.name} [{ch.unit}]" for ch in channels]
                        writer.writerow(names_row)

                        vals += [ch.samples for ch in channels]

                        for idx, row in enumerate(zip(*vals)):
                            writer.writerow(row)

                    del self._master_channel_cache[(i, 0, -1)]

        elif fmt == "mat":

            name = name.with_suffix(".mat")

            if not single_time_base:
                mdict = {}

                master_name_template = "DGM{}_{}"
                channel_name_template = "DG{}_{}"
                used_names = UniqueDB()

                for i, grp in enumerate(self.groups):
                    if self._terminate:
                        return

                    included_channels = self._included_channels(i)

                    master_index = self.masters_db.get(i, -1)

                    if master_index >= 0:
                        included_channels.add(master_index)

                    channels = self.select(
                        [(None, i, idx) for idx in included_channels]
                    )

                    for j, sig in zip(included_channels, channels):

                        if j == master_index:
                            channel_name = master_name_template.format(i, sig.name)
                        else:
                            if use_display_names:
                                channel_name = sig.display_name or sig.name
                            else:
                                channel_name = sig.name
                            channel_name = channel_name_template.format(i, channel_name)

                        channel_name = matlab_compatible(channel_name)
                        channel_name = used_names.get_unique_name(channel_name)

                        if sig.samples.dtype.names:
                            sig.samples.dtype.names = [
                                matlab_compatible(name)
                                for name in sig.samples.dtype.names
                            ]

                        mdict[channel_name] = sig.samples

            else:
                used_names = UniqueDB()
                mdict = {}

                for name in df.columns:
                    channel_name = matlab_compatible(name)
                    channel_name = used_names.get_unique_name(channel_name)

                    mdict[channel_name] = df[name].values

                mdict['time'] = df.index.values

            if format == "7.3":

                savemat(
                    str(name),
                    mdict,
                    long_field_names=True,
                    format="7.3",
                    delete_unused_variables=False,
                    oned_as=oned_as,
                )
            else:
                savemat(
                    str(name),
                    mdict,
                    long_field_names=True,
                    oned_as=oned_as,
                    do_compression=bool(compression),
                )

        elif fmt == "parquet":
            name = name.with_suffix(".parquet")
            if compression:
                write_parquet(name, df, compression=compression)
            else:
                write_parquet(name, df)

        else:
            message = (
                'Unsopported export type "{}". '
                'Please select "csv", "excel", "hdf5", "mat" or "pandas"'
            )
            message.format(fmt)
            logger.warning(message)