def __init__(self, mask_mode): if mask_mode not in ["NM", "M"]: print("mask_mode = " + str(mask_mode)) raise (ValueError, "ERROR: invalid parameters") self.mask_mode = mask_mode self.number_of_rows = GlobalizeResults.NUMBER_OF_ROWS[mask_mode] self.results_reader = ResultsReader('local', mask_mode) output_path, output_filename = ResultsPaths.get_path_and_filename( 'global', mask_mode) self.output_file = CSVWriter(output_path, output_filename) self.output_file.write_row(self.results_reader.read_line_no_count())
def run(): text_file = TextFileReader( "/Users/pablocerve/Documents/FING/Proyecto/datasets/[5]el-nino/large/data", "tao-all2.dat") csv_file1 = CSVWriter( "/Users/pablocerve/Documents/FING/Proyecto/pc-tesis/dataset_parser/scripts", "nino1.csv") csv_file2 = CSVWriter( "/Users/pablocerve/Documents/FING/Proyecto/pc-tesis/dataset_parser/scripts", "nino2.csv") row = [ "index_start", "index_end", "count", "timestamp_start", "timestamp_end", "min_lat", "max_lat", "min_long", "max_long", "dif_lat", "dif_long", "buoy_id" ] csv_file1.write_row(row) csv_file2.write_row(row) parser = ParserElNino() logger = setup_logger('el-nino.log', 'el-nino.log') df_utils = DataFrameUtils(parser, logger) script = Script(text_file, csv_file1, csv_file2, parser, df_utils) script.run_loop() script.close() path = "/Users/pablocerve/Documents/FING/Proyecto/pc-tesis/dataset_parser/scripts/[5]el-nino" filename = "el-nino.csv" df_utils.df_to_output_csv(path, filename)
def clean(): input_path = OSUtils.cpp_project_path() + "/test_files" input_filename = "noaa-adcp-201501.csv" output_path = OSUtils.cpp_project_path() + "/test_files" output_filename = "noaa-adcp-201501_2cols.csv" csv_reader = CSVReader(input_path, input_filename) csv_writer = CSVWriter(output_path, output_filename) iterate(csv_reader, csv_writer) csv_reader.close() csv_writer.close()
def df_to_output_csv(self, output_path, output_filename): output_file = CSVWriter(output_path, output_filename) output_file.write_row(['DATASET:', self.parser.NAME]) columns = ['Timestamp'] columns.extend(self.pandas_tools.df.columns) output_file.write_row(columns) self.pandas_tools.df_to_csv(output_file) output_file.close()
def __init__(self, output_filename, mask_mode): self.output_path = self.OUTPUT_PATH + datetime.now().strftime("%Y.%m.%d_%H.%M") + "/" os.mkdir(self.output_path) self.csv = CSVWriter(self.output_path, output_filename) self.mask_mode = mask_mode # "NM" or "M" # iteration vars self.logger = None self.output_dataset_path = None self.row = None self.thresholds_array = None self.input_path = None self.input_filename = None self.coder_dictionary = None self.output_dataset_coder_path = None
class DatasetAnalysisScript(object): OUT_PATH = "/Users/pablocerve/Documents/FING/Proyecto/pc-tesis/dataset_parser/scripts/informe/dataset_tables/out" COLUMNS = ["Dataset", "Column", "#Rows", None, "#N", "#N (%)", None, "Min", "Max", "Range", None, "Mean", "STD"] def __init__(self): self.debug_mode = True self.csv_writer = CSVWriter(self.OUT_PATH, 'output.csv') def run(self): self.csv_writer.write_row(self.COLUMNS) self.__datasets_iteration() def __datasets_iteration(self): for dataset_id, self.dataset_name in enumerate(ExperimentsUtils.DATASET_NAMES): self._print(self.dataset_name) self.csv_writer.write_row([ExperimentsUtils.get_dataset_short_name(self.dataset_name)]) self.__columns_iteration() def __columns_iteration(self): dataset_filenames = ProcessResults.dataset_filenames(self.dataset_name, False) for self.col_index in range(1, ExperimentsUtils.get_dataset_data_columns_count(self.dataset_name) + 1): self.col_name = ExperimentsUtils.COLUMN_INDEXES[self.dataset_name][self.col_index - 1] self._print(self.col_name, 1) self.column_dataframe = None self.__filenames_iteration(dataset_filenames) def __filenames_iteration(self, dataset_filenames): column_df = None for self.filename in dataset_filenames: self._print(self.filename, 2) column_df = DatasetAnalysis.append_df(self.dataset_name, self.filename, self.col_index, self.col_name, column_df) print column_df.shape DatasetAnalysis.print_df_analysis(column_df, self.csv_writer) def _print(self, value, spaces=0): if self.debug_mode: print " " * (spaces * 2) + value
from file_utils.csv_utils.csv_reader import CSVReader from file_utils.csv_utils.csv_writer import CSVWriter mask_true_path = OSUtils.python_project_path( ) + "/scripts/compress/output/pwlh-vs-pwlhint-mask-true" mask_false_path = OSUtils.python_project_path( ) + "/scripts/compress/output/pwlh-vs-pwlhint-mask-false" path = mask_true_path pwlh_filename = "results-pwlh.csv" pwlh_int_filename = "results-pwlh-int.csv" results_filename = "pwlh_vs_pwhl_int.csv" csv_reader_pwlh = CSVReader(path, pwlh_filename) csv_reader_pwlh_int = CSVReader(path, pwlh_int_filename) csv_writer_results = CSVWriter(path, results_filename) assert (csv_reader_pwlh.total_lines == csv_reader_pwlh_int.total_lines) def compare_lines(a, b, c): return compare_lines_(a, b, c) def run(): while csv_reader_pwlh.continue_reading: assert (csv_reader_pwlh.current_line_count == csv_reader_pwlh_int.current_line_count) current_line_count = csv_reader_pwlh.current_line_count line_pwlh = csv_reader_pwlh.read_line()
class CompressScript: COMPRESS_PATH = OSUtils.git_path() + "/dataset_parser/scripts/compress" OUTPUT_PATH = COMPRESS_PATH + "/output/" DATASETS_PATH = ExperimentsUtils.CSV_PATH MAX_HEADER_SIZE = 15000 def __init__(self, output_filename, mask_mode): self.output_path = self.OUTPUT_PATH + datetime.now().strftime("%Y.%m.%d_%H.%M") + "/" os.mkdir(self.output_path) self.csv = CSVWriter(self.output_path, output_filename) self.mask_mode = mask_mode # "NM" or "M" # iteration vars self.logger = None self.output_dataset_path = None self.row = None self.thresholds_array = None self.input_path = None self.input_filename = None self.coder_dictionary = None self.output_dataset_coder_path = None def run(self): row = ['Dataset', 'Filename', '#rows', 'Coder', '%', 'Error Threshold', 'Window Param', 'Size (B)', 'CR (%)', 'Delta - Size (data)', 'Delta - Size (mask)', 'Delta - Size (total)', 'Delta - CR (%)', 'Other columns - Size (data)', 'Other columns - Size (mask)', 'Other columns - Size (total)', 'Other columns - CR (%)'] self.csv.write_row(row) for dataset_dictionary in ExperimentsUtils.DATASETS_ARRAY: self._run_script_on_dataset(dataset_dictionary) self.csv.close() def _run_script_on_dataset(self, dataset_dictionary): self.input_path = self.DATASETS_PATH + dataset_dictionary['folder'] logger_name = dataset_dictionary['name'].lower() + '.log' logger_filename = self.output_path + logger_name self.logger = setup_logger(logger_name, logger_filename) self.output_dataset_path = self.output_path + dataset_dictionary['o_folder'] create_folder(self.output_dataset_path) dataset_name = dataset_dictionary['name'] for file_index, self.input_filename in enumerate(ExperimentsUtils.dataset_csv_filenames(dataset_name)): self.row = [dataset_name] if file_index == 0 else [None] self._run_script_on_file(file_index) def _run_script_on_file(self, file_index): print(self.input_path + "/" + self.input_filename) base_values = None row_count = PrintUtils.separate(CSVUtils.csv_row_count(self.input_path, self.input_filename)) # calculate error thresholds compress_utils = CompressUtils(self.COMPRESS_PATH, self.input_path, self.input_filename) self.thresholds_array = compress_utils.get_thresholds_array() coders_array = ExperimentsUtils.coders_array(self.mask_mode) for coder_index, self.coder_dictionary in enumerate(coders_array): if self._skip_iteration(): continue if file_index == 0 and coder_index == 0: # first row of dataset and file self.row += [self.input_filename, row_count] elif coder_index == 0: # first row of file self.row = [None, self.input_filename, row_count] else: self.row = [None, None, None] base_values = self._run_script_on_coder(base_values) def _skip_iteration(self): # TODO: uncomment in ubuntu # if self.input_filename == "el-nino.csv" and self.coder_dictionary['name'] == "CoderGAMPS": # return True # TODO: uncomment in mac # if self.input_filename != "el-nino.csv" or self.coder_dictionary['name'] not in ["CoderBase", "CoderGAMPS"]: # return True return False def _run_script_on_coder(self, base_values): self.output_dataset_coder_path = self.output_dataset_path + '/' + self.coder_dictionary['o_folder'] create_folder(self.output_dataset_coder_path) coder_name = self.coder_dictionary['name'] if coder_name == 'CoderBase': base_values = self._run_script_on_base_coder(base_values) else: self._run_script_of_other_coders(base_values) return base_values def _run_script_on_base_coder(self, base_values): values = [self.coder_dictionary['name']] + [None] * 3 compress_args = CompressArgs(self) compression_values = CompressScript._compress_file(compress_args) base_values = self._out_results(base_values, compression_values, self.row + values) return base_values def _run_script_of_other_coders(self, base_values): window_param_name = list(self.coder_dictionary['params'].keys())[0] # there's a single key window_sizes = self.coder_dictionary['params'][window_param_name] for thre_index, threshold_entry in enumerate(self.thresholds_array): percentage = threshold_entry['percentage'] error_thresold_array = threshold_entry['values'] params = {'error_threshold': error_thresold_array} for win_index, window_size in enumerate(window_sizes): values = [self.coder_dictionary['name']] if thre_index == 0 and win_index == 0 else [None] values += [percentage, params['error_threshold']] if win_index == 0 else [None, None] values += [window_size] params[window_param_name] = window_size compress_args = CompressArgs(self, params) compression_values = CompressScript._compress_file(compress_args) base_values = self._out_results(base_values, compression_values, self.row + values) return base_values @staticmethod def _compress_decompress_compare(args): print("Compressing and decompressing files...") coder_info, header_bits, columns_bits, column_mask_bits = CompressCPP.code_decode_cpp(args) print("Comparing original and decompressed files...") csv_compare = CSVCompare(args.input_path, args.input_filename, args.output_path, args.deco_filename) # TODO: the csv comparison would be faster if implemented in C++ same_file = csv_compare.compare(args.coder_params.get('error_threshold'), False) assert same_file # NEVER COMMENT THIS LINE return [coder_info, header_bits, columns_bits, column_mask_bits, same_file] @staticmethod def _compress_file(args): coder_info, header_bits, columns_bits, column_mask_bits, same_file = CompressScript._compress_decompress_compare(args) # print results input_file = args.input_path + "/" + args.input_filename compressed_file = args.output_path + "/" + args.compressed_filename compressed_size = CompressScript._print_results(coder_info, args.logger, input_file, compressed_file, same_file) CompressScript._size_check(compressed_size, header_bits, columns_bits, column_mask_bits) compression_values = [] for i in range(0, len(columns_bits)): compression_values.append(columns_bits[i]) compression_values.append(column_mask_bits[i]) compression_values.append(columns_bits[i] + column_mask_bits[i]) return [compressed_size] + compression_values @staticmethod def _print_results(coder_info, logger, input_file, compressed_file, same_file): input_size = os.path.getsize(input_file) compressed_size = os.path.getsize(compressed_file) logger.info("") logger.info("RESULTS") if same_file: logger.info("--------------------------(same file!)") else: logger.info("ERROR: DIFFERENT FILES!") logger.info(coder_info) logger.info("TIME: " + datetime.now().strftime("%Y-%m-%d %H:%M:%S")) logger.info("ORIGINAL FILE:") logger.info("-> name: %s" % input_file) logger.info("-> size (bytes): %s" % "{:,}".format(input_size)) logger.info("COMPRESSED FILE:") logger.info("-> name: %s" % compressed_file) logger.info("-> size (bytes): %s" % "{:,}".format(compressed_size)) logger.info("-> %s%% of original" % PrintUtils.percentage(compressed_size, input_size)) logger.info("") return compressed_size @staticmethod def _size_check(compressed_size, header_bits, columns_bits, column_mask_bits): bits_sum = header_bits + sum(columns_bits) + sum(column_mask_bits) bytes_sum = (bits_sum + 7) // 8 if compressed_size != bytes_sum: print("compressed_size " + str(compressed_size)) print("bytes_sum " + str(bytes_sum)) assert(compressed_size == bytes_sum) header_bytes = (header_bits + 7) // 8 max_header_size = CompressScript.MAX_HEADER_SIZE if header_bytes >= max_header_size: print('header_bytes = %s' % header_bytes) assert(header_bytes < max_header_size) def _out_results(self, base_values, compression_values, row): values = [] if base_values is None: base_values = compression_values for idx, value in enumerate(compression_values): if (idx % 3) == 0: # idx is 0, 3, 6, 9, 12, etc. val = PrintUtils.separate(value) if idx == 0 else value values += [val, 100] else: values += [value] else: for idx, value in enumerate(compression_values): if (idx % 3) == 0: # idx is 0, 3, 6, 9, 12, etc. percentage = PrintUtils.percentage(value, base_values[idx]) val = PrintUtils.separate(value) if idx == 0 else value values += [val, PrintUtils.separate(percentage)] else: values += [value] self.csv.write_row(row + values) return base_values
import sys sys.path.append('.') from file_utils.csv_utils.csv_writer import CSVWriter from file_utils.csv_utils.csv_reader import CSVReader path = "/Users/pablocerve/Documents/FING/Proyecto/pc-tesis/dataset_parser/scripts/informe/results/3.1/06.2020/2-complete" file = "results-mm3.csv" new_file = "results-mm3-p.csv" reader = CSVReader(path, file) writer = CSVWriter(path, new_file) while reader.continue_reading: line = reader.read_line() if "0" in line[4]: line[4] = int(float(line[4]) * 100) writer.write_row(line) writer.close() reader.close()
def __common_create_column_csv(self): dataset_columns_count = ExperimentsUtils.get_dataset_data_columns_count(self.dataset_name) reader = CSVReader(ExperimentsUtils.get_dataset_path(self.dataset_name), self.filename) writer = CSVWriter(self.compress_path, self.column_filename) return dataset_columns_count, reader, writer
class Writer1(object): def __init__(self, path, extra_str, mode): self.file = CSVWriter(path, extra_str + '-process1.csv') self.write_first_row() self.data_rows = [] self.data = {} self.writer_min_max = TableMinMax(path, mode) def write_first_row(self): row = ["Dataset", "Filename", "Column", "Coder"] row += 2 * (ExperimentsUtils.THRESHOLDS + ['']) row += ExperimentsUtils.THRESHOLDS + ['WORST', '' ] + ExperimentsUtils.THRESHOLDS self.file.write_row(row) def write_dataset_name(self, dataset_name): self.file.write_row(([dataset_name])) def write_filename(self, filename): self.file.write_row(['', filename]) def write_col_name(self, col_name): self.file.write_row(['', '', col_name]) def save_data_row(self, coder_name, windows, percentages, total_bits): data_row = { 'coder_name': coder_name, 'windows': windows, 'percentages': percentages, 'total_bits': total_bits } self.data_rows.append(data_row) def write_data_rows(self): self._calculate_relative_differences() for row in self.data_rows: coder_name, windows, = row['coder_name'], row['windows'] percentages, total_bits = row['percentages'], row['total_bits'] relative_diffs = row['relative_diffs_string'] worst_relative_diff = row['worst_relative_diff'] worst_relative_diff_string = row['worst_relative_diff_string'] row = ['', '', '', coder_name] + windows + ['' ] + percentages + [''] row += relative_diffs + [worst_relative_diff_string, '' ] + total_bits self.file.write_row(row) if coder_name not in self.data: self.data[coder_name] = [] self.data[coder_name].append(worst_relative_diff) self.writer_min_max.save_data_rows(self.data_rows) self.data_rows = [] def show_data(self): for key in self.data: max_rd = max(self.data[key]) print(self.format_rd(max_rd) + ' <= ' + key) self.writer_min_max.show_data() def _calculate_relative_differences(self): for row in self.data_rows: row['relative_diffs'] = [] row['relative_diffs_string'] = [] for threshold_index in range(len(ExperimentsUtils.THRESHOLDS)): for row in self.data_rows: smallest = self._smallest_total_bits(threshold_index) total_bits = row['total_bits'][threshold_index] rd = MathUtils.relative_difference(total_bits, smallest) rd_string = self.format_rd(rd) row['relative_diffs'].append(rd) row['relative_diffs_string'].append(rd_string) self._calculate_worst_relative_diff() def _calculate_worst_relative_diff(self): for row in self.data_rows: # row['relative_diffs'] = [row['relative_diffs'][0]] # ONLY LOSSLESS # row['relative_diffs'] = row['relative_diffs'][1:] # ONLY LOSSY worst_rd = max(row['relative_diffs']) row['worst_relative_diff'] = worst_rd row['worst_relative_diff_string'] = self.format_rd(worst_rd) def _smallest_total_bits(self, threshold_index): smallest = None for row in self.data_rows: total_bits = row['total_bits'][threshold_index] if smallest is None or total_bits < smallest: smallest = total_bits return smallest def write_row(self, row): self.file.write_row(row) @staticmethod def format_rd(rd): return "%0.2f" % rd
def df_to_output_csv(self, output_path, output_filename): # print stats self.pandas_tools.print_stats() # output to file output_file = CSVWriter(output_path, output_filename) output_file.write_row(['DATASET:', self.parser.NAME]) output_file.write_row(['TIME UNIT:', 'hours']) output_file.write_row( ['FIRST TIMESTAMP:', self.pandas_tools.first_timestamp()]) row = ['Time Delta'] row.extend(self.pandas_tools.df.columns) output_file.write_row(row) self.pandas_tools.df_to_csv(output_file, 'hours') output_file.close()
class GlobalizeResults(object): # NUMBER_OF_ROWS = {"NM": 393, "M": 457} NUMBER_OF_ROWS = {"NM": 393 - 7 * 8, "M": 7 * 8 * 8 + 1} def __init__(self, mask_mode): if mask_mode not in ["NM", "M"]: print("mask_mode = " + str(mask_mode)) raise (ValueError, "ERROR: invalid parameters") self.mask_mode = mask_mode self.number_of_rows = GlobalizeResults.NUMBER_OF_ROWS[mask_mode] self.results_reader = ResultsReader('local', mask_mode) output_path, output_filename = ResultsPaths.get_path_and_filename( 'global', mask_mode) self.output_file = CSVWriter(output_path, output_filename) self.output_file.write_row(self.results_reader.read_line_no_count()) def run(self): for dataset_obj in ExperimentsUtils.DATASETS_ARRAY: self.__globalize_dataset(dataset_obj['name']) def __globalize_dataset(self, dataset_name): filenames = ExperimentsUtils.dataset_csv_filenames(dataset_name) if len(filenames) == 1: print(dataset_name + " - single file") self.multiple_files = False else: print(dataset_name + " - multiple files") self.multiple_files = True self.__globalize_filenames(dataset_name, filenames) def __globalize_filenames(self, dataset_name, filenames): # "NM" => CoderBase coder_base_line = self.__get_coder_base_line(dataset_name, filenames) coder_base_line_with_percentages = ResultsReader.set_percentages( coder_base_line, coder_base_line) self.output_file.write_row(coder_base_line_with_percentages) # "M" => CoderBase, CoderPCA, CoderAPCA, etc. other_coders_lines = self.__get_other_coders_lines( dataset_name, filenames) GlobalizeResults.write_other_coders_lines(self.output_file, coder_base_line, other_coders_lines) def __get_coder_base_line(self, dataset_name, filenames): results_array = self.__results_array(dataset_name, filenames, CSVConstants.INDEX_ALGORITHM) for entry in results_array: assert (len(entry) == 1) return self.__mask_results_lines(results_array)[0] def __get_other_coders_lines(self, dataset_name, filenames): results_array = self.__results_array(dataset_name, filenames) for entry in results_array: assert (len(entry) == self.number_of_rows) return self.__mask_results_lines(results_array) def __mask_results_lines(self, results_array): new_lines = [] number_of_rows = len(results_array[0]) for index in range(number_of_rows): new_line = None for file_results in results_array: # print file_results file_results_line = file_results[index] file_results_line = GlobalizeResults.convert_line( file_results_line, self.multiple_files) new_line = file_results_line if new_line is None else self.__merge_lines( new_line, file_results_line) new_lines.append(new_line) assert (len(new_lines) == number_of_rows) return new_lines @staticmethod def __merge_lines(line1, line2): CSVConstants.check_lines(line1, line2) skip_index = [CSVConstants.INDEX_WINDOW, CSVConstants.INDEX_THRESHOLD] for index in range(len(line1)): if CSVConstants.is_percentage_index(index) or index in skip_index: pass elif isinstance(line1[index], int): line1[index] += line2[index] return line1 def __results_array(self, dataset_name, filenames, change_index=CSVConstants.INDEX_FILENAME): results = [] for filename in filenames: filename_results = self.results_reader.filename_results( dataset_name, filename, change_index) results.append(filename_results) assert (len(results) == len(filenames)) return results @staticmethod def compare_files(path_1, filename_1, path2, filename_2): compare = filecmp.cmp(path_1 + "/" + filename_1, path2 + "/" + filename_2) if compare: print("SAME!") assert compare @staticmethod def convert_line(line, global_mode=True): new_line = ResultsReader.convert_line(line) if global_mode: filename = new_line[1] new_filename = 'Global' if len(filename) > 0 else filename new_line[1] = new_filename return new_line @staticmethod def write_other_coders_lines(output_file, coder_base_line, other_coders_lines): for index, line in enumerate(other_coders_lines): if index > 0: # Ignore CoderBase line_with_percentages = ResultsReader.set_percentages( line, coder_base_line) output_file.write_row(line_with_percentages)
def write_csv(rows): csv_writer = CSVWriter(path, filename) for row in rows: csv_writer.write_row(row) csv_writer.close()
def __init__(self): self.debug_mode = True self.csv_writer = CSVWriter(self.OUT_PATH, 'output.csv')
def df_to_output_csv(self, output_path, output_filename): if self.pandas_tools.is_empty_df(): return output_file = CSVWriter(output_path, output_filename) output_file.write_row(['DATASET:', self.parser.name]) output_file.write_row(['TIME UNIT:', self.parser.time_unit]) output_file.write_row( ['FIRST TIMESTAMP:', self.pandas_tools.first_timestamp()]) output_file.write_row(['Time Delta'] + self.parser.columns) self.pandas_tools.df_to_csv(output_file, self.parser.time_unit) output_file.close()
def create_csv_writer(): path = "/Users/pablocerve/Documents/FING/Proyecto/results/avances-8" filename = "p,k.csv" return CSVWriter(path, filename)
def compare_pca_results(): original = CSVReader(pca_mask_folder, "results-original.csv") results = CSVReader(pca_mask_folder, "results-mask.csv") csv_writer = CSVWriter(pca_mask_folder, "results-merge.csv") assert (original.total_lines == results.total_lines) while original.continue_reading: original_line = original.read_line() results_line = results.read_line() coder_name = original_line[3] if coder_name in ["Coder", "CoderBase"]: # assert(original_line == results_line) csv_writer.write_row(parse_line(original_line)) else: if len(original_line[4]) > 0: # algorithm params line original_line, results_line = write_params_line( csv_writer, original_line, results_line) original_line = parse_line(original_line) results_line = parse_mask_line(results_line) # if original_line == results_line: # continue csv_writer.write_row(['O'] + original_line[1:] + ['O']) csv_writer.write_row(['M'] + results_line[1:] + ['M']) diff = [] for i in range(7, len(original_line)): original_value, results_value = original_line[i], results_line[ i] if i % 2 == 0: # floats (percentages) # diff_value = results_value + ' - ' + original_value diff_value = float(results_value) - float(original_value) diff_value = diff_scenarios(diff_value) else: # integers (bits) if original_value == results_value: diff_value = '===' else: diff_value = c_int(results_value) - c_int( original_value) diff_value = '+++' + str( diff_value) if diff_value > 0 else '---' + str( diff_value) diff.append(diff_value) diff_line = original_line[:7] + diff csv_writer.write_row(diff_line) original.close() results.close() csv_writer.close()
def __init__(self, path, extra_str, mode): self.file = CSVWriter(path, extra_str + '-process1.csv') self.write_first_row() self.data_rows = [] self.data = {} self.writer_min_max = TableMinMax(path, mode)