def write_output(self, f_out, f_in): """Assemble output file with collected results.""" out = csv.writer(f_out, dialect='excel', delimiter=';') write = out.writerow mdpair = self.get_mdpair() mdpts = self.get_mdpair_coords() write(['input filename', filename(f_in)]) write([]) write(['distance results']) write(['largest distance points (indices)', str(mdpair)]) write(['coordinates of point %s' % mdpair[0], mdpts[0]]) write(['coordinates of point %s' % mdpair[1], mdpts[1]]) write(['distance', str(self.get_edm()[mdpair])]) write([]) write(['area results calculated by triangular tesselation']) write(['longest transversal edge', self.get_longest_edge_len()]) write(['overall area', self.get_area()]) write(['perimeter', self.perimeter])
def __init__(self, xmlfile, namespace=''): """Create a new Imaris-XML object from a file. Parameters ---------- xmlfile : file or str A filehandle or string for the XML file to parse. namespace : string, optional A string denoting the namespace expected in the XML file, defaults to the one used by MS Excel in its XML format. """ self.tree = None self.cells = {} # by default, we expect the namespace of Excel XML: self.namespace = 'urn:schemas-microsoft-com:office:spreadsheet' if namespace: self.namespace = namespace log.info("Parsing XML file: %s" % filename(xmlfile)) self.tree = etree.parse(xmlfile) log.info("Done parsing XML: %s" % self.tree) self._check_namespace()
def gen_stats(f_in, f_out, label=False, deltas=[1], thresh=0, verbosity=0): """Parse and process tracks and calculate statistics from the data.""" # default loglevel is 30 while 20 and 10 show more details loglevel = (3 - verbosity) * 10 log.setLevel(loglevel) log.warn("Infile: %s" % f_in) log.debug("Outfile: %s" % f_out) log.info("Stepping width(s): %s" % deltas) log.info("Angle threshold: %s" % thresh) ppr = pprint.PrettyPrinter(indent=4) ######### tracks parsing ######### # TODO: parsing can be done in a nicer way be reading the header lines via # csvreader.next(), checking for the expected values and the number of # tracks and then directly reading the trackpoints into a numpy ndarray... mtrack2_file = filehandle(f_in, "r") csvreader = csv.reader(mtrack2_file, delimiter="\t") # parse all lines into memory # NOTE: this is bad if the files get too large, but we haven't seen result # files from MTrack2 that are bigger than a couple of MB. data = [] for row in csvreader: data.append([parse_cell(x) for x in row]) # data.append(row) # start parsing the header header = [] header.append(data.pop(0)) header.append(data.pop(0)) if not header[0][0] == "Frame": # exit because file is broken... raise SystemExit("Unable to find correct header, stopping.") log.debug("Header:\n%s\n" % ppr.pformat(header)) # second line is 'Tracks 1 to N', so we can read the total number there: trackmax = int(header[1][0].split(" ")[3]) log.info("Total number of tracks: %s" % ppr.pformat(trackmax)) # last N lines are the stats per track trackstats = [] while True: # pop returns the last element if no index is given cur = data.pop() if cur[0] == "Track": # remove one more line (empty), then we're done cur = data.pop() break else: trackstats.append(cur) # as we parsed from the last element, we need to reverse the list trackstats.reverse() log.warn("Track statistics:\n%s" % ppr.pformat(trackstats)) # this code can help debugging problematic files: # for row in data: # try: # np.array(row, dtype='float') # except ValueError: # raise SystemExit(row) # create the ndarray from the remaining data while removing column 0 # (indices), and every subsequent third column (flags) todelete = range(0, (trackmax + 1) * 3, 3) npdata = np.delete(data, todelete, axis=1) npdata_bool = npdata > 0 ######### tracks processing (combining etc.) ######### tracklen = [0] * trackmax t_overlap = npdata_bool[:, 0] for track in range(trackmax): tracklen[track] = sum(npdata_bool[:, track * 2]) t_overlap = t_overlap * npdata_bool[:, track * 2] if trackmax > 1 and sum(t_overlap) > 0: raise SystemExit("*** WARNING: Found overlapping tracks! ***") t_combined = np.zeros((npdata.shape[0], 2)) for track in range(trackmax): t_combined += npdata[:, track * 2 : (track + 1) * 2] comb_mask = np.zeros(t_combined.shape[0]) for i, row in enumerate(t_combined): if (row == [0.0, 0.0]).all(): # print 'row %i is zerooooo' % i comb_mask[i] = True t_combined = np.ma.compress_rows(np.ma.array(t_combined, mask=np.repeat(comb_mask, 2))) ######### calculations ######### mov_v = {} mov_n = {} rot = {} rot_t = {} outdata = t_combined if label: label = "pos_x\tpos_y" for step in deltas: # calculate movement vectors (mov_v): mov_v[step] = movement_vectors(t_combined, step) # calculate vector normals (mov_n): mov_n[step] = np.zeros((mov_v[step].shape[0], 1)) for pos in range(1, mov_n[step].shape[0]): mov_n[step][pos] = np.linalg.norm(mov_v[step][pos]) # calculate rotation: rot[step] = calc_rotation(mov_v[step], mov_n[step], step) # for the movement vectors all values need to be written to the output, # but it is not necessary to repeat them for every stepping, so they # are only added for stepping '1': if step == 1: outdata = np.hstack((outdata, mov_v[1])) if label: label += "\tdelta_x\tdelta_y" outdata = np.hstack((outdata, mov_n[step], rot[step])) # threshold rotation angles: if thresh > 0: rot_t[step] = np.where(abs(rot[step]) > thresh, rot[step], 0) outdata = np.hstack((outdata, rot_t[step])) if label: label += "\tdistance_%s\tangle_%s" % (step, step) if thresh > 0: label += "\tthresholded_angle_%s" % step if label: log.info("label: %s" % label) _save_results(f_out, outdata, label) log.warn("Wrote results to '%s'" % filename(f_out))