def choose_submenu(prompt, selection_pairs): """ Asks the user a multiple choice question, returns the object paired with selected option. :prompt: The string above list of choices (Typically the question). :selection_pair: 2D iterable (e.g. list of tuples), where: each row is a choice, column 0 is the string displayed as that choice to the user, and column 1 is the object returned if that choice is selected. """ while True: print(prompt) i = 0 # define i in this scope so we can use it later for pair in selection_pairs: i += 1 print("{:2}) {}".format(i, pair[0])) try: user_choice = input("> ").strip() user_choice = int(user_choice) user_choice -= 1 # convert to zero index assert user_choice < stats.count(selection_pairs) return selection_pairs[user_choice][1] except ( ValueError, AssertionError ): # User enters something that's not an int, or User enters invalid number print("'%s' not valid selection, type a number between 1 and %d" % (user_choice, i))
def add_data_menu(): """user enters data manually""" global data_x, data_y, unsaved_changes single_column = num_columns() == 1 prior_data_len = 0 if num_columns() == 0: # no data yet single_column = choose_submenu( "Create new data set with one or two columns?", [("One", True), ("Two", False), ("Back", None)]) if single_column == None: # user selected cancel return # Create new data since none loaded if not single_column: data_y = [] data_x = [] else: prior_data_len = stats.count(data_x) # update to currently loaded data if single_column: # only x values while True: try: x = (input("enter value (or 'q' to quit)\n> ")) if x == 'q': break else: data_x.append(float(x)) except ValueError: print("Value not recognized, enter only numbers") else: # both x and y values while True: try: x = input("enter x value (enter 'q' to quit)\n> ") if x == 'q': break x = float(x) y = float(input("enter corresponding y value\n> ")) data_x.append(x) data_y.append(y) except ValueError: print("Value not recognized, enter only numbers") if stats.count( data_x ) != prior_data_len: # changes made if more data points than before unsaved_changes = True if stats.count(data_x) == 0: # check if empty data set data_x = None # data as None means no data loaded; leaving data as an empty array can cause ZeroDivision and other errors elsewhere data_y = None
def stats_strings(x, y=None): r""" takes one or two lists of data and returns string (containing \n characters) of all stats functions and their values. prints y data as second column to the right of x column. """ output = "" funcs = [ "mean", "median", "mode", "variance", "standard_dev", "min", "max", "range2" ] right_width = 6 # number of characters for value on right side of equals sign left_width = 12 dec_prec = 2 # number of decimal places column_padding = 8 * " " # between x and y columns # the following lines evaluate each func (e.g. "mean" becomes stats.mean(x)), with the func's name and result put into formatted string. for func in funcs: output += "x {:{lw}} = {:>{rw}.{dp}f}".format(func, eval("stats." + func + "(x)"), lw=left_width, rw=right_width, dp=dec_prec) if y != None: output += column_padding + "y {:{lw}} = {:>{rw}.{dp}f}".format( func, eval("stats." + func + "(y)"), lw=left_width, rw=right_width, dp=dec_prec) output += "\n" # count, the only integer stat, needs ever so slightly differnt format string. output += "x {:{lw}} = {:>{rw}d}".format("count", stats.count(x), lw=left_width, rw=right_width) if y != None: output += column_padding + "y {:{lw}} = {:>{rw}d}".format( "count", stats.count(x), lw=left_width, rw=right_width) output += "\n" return output
def histogram_subplots(username, xlist, ylist, save_picture): """This one will print out two histograms, side by side, displaying x's and y's individually""" plt.subplot(1, 2, 1) bins = int(stats.count(xlist) / 10) bins = stats.min((bins, 50)) bins = stats.max((bins, 5)) plt.hist(xlist, bins=bins, color='maroon') plt.title("%s data" % ("x")) plt.xlabel('x values') plt.ylabel('frequency') plt.subplot(1, 2, 2) bins = int(stats.count(ylist) / 10) bins = stats.min((bins, 50)) bins = stats.max((bins, 5)) plt.hist(ylist, bins=bins, color='maroon') plt.title("%s data" % ("y")) plt.xlabel('y values') plt.ylabel('frequency') if save_picture: savefig_as_jpeg(username, 7) plt.show()
def histogram(username, alist, save_picture, is_data_for_y=False): ''' function histogram takes in a list, returns a histogram of the values in the list, plot has title and axes. :is_data_for_x: is a Boolean that specifies if data is from x or y, so that file can be saved with correct figure number ''' bins = int(stats.count(alist) / 10) bins = stats.min((bins, 50)) bins = stats.max((bins, 5)) plt.hist(alist, bins=bins, color='maroon') plt.title("%s data" % ("y" if is_data_for_y else "x")) plt.xlabel('value') plt.ylabel('frequency') if save_picture: savefig_as_jpeg( username, int(is_data_for_y)) # figure 0 or 1 for x or y respectively plt.show()
def _start_recording(self, data): self.logger.info('Recording started!') self._frames.append(data) start = datetime.datetime.now() self._record_start_dt = start stop = start + datetime.timedelta(seconds=self._min_record_time) while datetime.datetime.now() < stop: data = self._stream.read(self._CHUNK) self._frames.append(data) if self._check_noise_lvl(data): stop = datetime.datetime.now() + datetime.timedelta( seconds=self._min_record_time) saved_file, date, record_time = self._save() if saved_file: self.logger.info('Recording finished! {}'.format(saved_file)) subject = '[WOOF-REPORTER] {}-{}'.format(date, record_time) self.sender.send_message_with_attachments(subject, message=count(date), file_path=saved_file) else: self.logger.info('Record lasted less than 2 seconds...')
def save_menu(): """ This is the menu that asks for the name of the function then how you would like to save it. Will spit back any errors you you have while trying to save it too, with no respect for your dignity """ global unsaved_changes if num_columns() == 0: print("No data to save!") return while True: output_name = input('what is the desired output file name?\n> ') try: with open(output_name + '.txt', "w") as output_file: output_file.write('Input file name: ' + inputfile.file_name + OUR_FILE_EXTEN + ' ||| Output file name: ' + output_name + '.txt ||| Username: '******' ||| Date and time: ' + str(datetime.datetime.now()) + '\n') output_file.write( stats_strings(data_x, data_y if num_columns() == 2 else None) + '\n') for i in range(stats.count(data_x)): if num_columns() == 1: output_file.write(str(data_x[i])) else: output_file.write( str(data_x[i]) + ',' + str(data_y[i])) output_file.write("\n") unsaved_changes = False print("File successfully saved") break except OSError as err: print("Unable to save:", err) if not prompt_yes_no("Would you like to retry saving?"): break
def inputfile(): global file_name while True: raw_in = input("Enter file path (or enter 'c' to cancel):\n> ").strip() if raw_in.lower() == "c": break raw_in = raw_in.rsplit('.', 1) if stats.count(raw_in) != 2: print("Invalid file path, must include an extension (e.g. '.txt')") continue file_name, file_type = raw_in try: # below is code for text file, appends each line (number) to a list after converting to float if file_type == 'txt'.lower(): with open(file_name + '.txt', 'r') as infile: data = infile data_x = [] data_y = [] # loop through data, check for headers, then strip unnecessary characters from numbers, then convert to floats and into lists for line in data: if line[0].isnumeric() or line[0] == '-': if ',' in line: line = line.split(',') line[0].strip('"') line[1].replace('"', '') line[1].strip('\n') try: x = float(line[0]) y = float(line[1]) data_x.append(x) data_y.append(y) except ValueError: continue else: data_x.append(float(line)) data_y = None else: pass # below is code for csv/tsv file, appends each line(number) to a list after converting to float elif csv_tsv(file_type) != 'stop': with open(file_name + '.' + file_type, 'r') as infile: data = infile data_x = [] data_y = [] # strips unnecessary characters from files, then convert to float, then append to list for line in data: if csv_tsv(file_type) == 'stop': break elif csv_tsv(file_type) in line: line = line.split(csv_tsv(file_type)) line[0] = line[0].strip('"') line[1] = line[1].replace('"', '') line[1] = line[1].strip('\n') try: data_x.append(float(line[0])) data_y.append(float(line[1])) except ValueError: # skip unreadable lines continue else: data_x.append(float(line)) data_y = None if stats.count(data_x) == 0: print("No readable data in file") else: raise ValueError( "Unrecognized file extension, use .txt, .csv, or .tsv") return data_x, data_y except (OSError, ValueError) as err: print(err)