def add_file(self, FF, fname='', idx_pos=None): """ Add a 'file_grid_netcc' obj. FF is an instance of the 'file_grid_netcc' class. Basically, won't use idx_pos property, most likely """ if not (fname): fname = FF.file_inp else: FF.file_inp = fname if fname: ab.IP("Adding {}".format(fname)) else: ab.IP("Adding unnamed file") # 1 if nothing prior, 2 if things exist and we are OK, exit if bad OK_TO_GO = self.check_new_file_with_current(FF) if idx_pos == None: idx_pos = self.nfile self.all_file[idx_pos] = FF self.all_fname[idx_pos] = fname self.all_idx.append(idx_pos) self.nfile += 1
def write_files_from_bval_bvec(B, VEC, prefix): """Input B :list of N bvals VEC :list of N grads (unscaled) prefix :basename of output Write out: + prefix_rvec.dat :row-format of N unscaled grads + prefix_bval.dat :row-format of N bvalues + prefix_cvec.dat :row-format of N *scaled* grads """ N = len(B) # row vec of grads fname = prefix + '_rvec.dat' fff = open(fname, 'w') for jj in range(3): for ii in range(N): fff.write(" {:>10.5f} ".format(VEC[ii][jj])) if jj != 2: fff.write("\n") fff.close() ab.IP("Wrote unscaled row vecs : {}".format(fname)) # row bvals fname = prefix + '_bval.dat' fff = open(fname, 'w') for ii in range(N): fff.write(" {:>10.3f} ".format(B[ii])) fff.close() ab.IP("Wrote b-value row file : {}".format(fname)) # col vec of grads fname = prefix + '_cvec.dat' fff = open(fname, 'w') for ii in range(N): for jj in range(3): fff.write(" {:>10.3f} ".format(VEC[ii][jj] * B[ii])) if jj != N - 1: fff.write("\n") fff.close() ab.IP("Wrote b-scaled col vecs : {}".format(fname))
def read_table_mat_GoN(self): '''Read all the matrix info in the main part of the table each matrix has a "matrix label" part self.nroi, self.nmat as well as string labels and integer ROI values We guess whether matrix element type is int or float based on whether a matrix has any '.' in it or not (respectively). ''' # starting point from which to read, verily idx = self.header_len self.allmat_labs = [] self.allmat = {} while idx < self.data_len: # first, the matrix label line line = [x.strip() for x in self.data[idx].split("#")] mat_lab = line[-1] ab.IP("Getting matrix: {}".format(mat_lab)) self.allmat_labs.append(mat_lab) idx += 1 # then, the matrix lines count_dots = 0 # use this as a way to tell int vs float M = [] for ii in range(self.nroi): count_dots += self.data[idx + ii].count('.') line = [x.strip() for x in self.data[idx + ii].split()] M.append(line) if count_dots: self.allmat[mat_lab] = mat2d(M, label=mat_lab, eletype=float, col_strlabs=self.roi_strlabs, row_strlabs=self.roi_strlabs, col_intvals=self.roi_intvals, row_intvals=self.roi_intvals) else: self.allmat[mat_lab] = mat2d(M, label=mat_lab, eletype=int, col_strlabs=self.roi_strlabs, row_strlabs=self.roi_strlabs, col_intvals=self.roi_intvals, row_intvals=self.roi_intvals) idx += ii + 1 if len(self.allmat_labs) != self.nmat: ab.EP("Mismatch in number of matrix labels {} and\n" "purported number of matrices in the file {}" "".format(self.allmat_labs, self.nmat))
def guess_appropriate_title_fontsize(self): """Similar goal/premise as guess_appropriate_figsize(). This if for the cbar values. Assumes the fig height is known at this point (so would have to be calc'ed after guess_appropriate_figsize(), potentially. """ good_val = 3 + 1.1 * (0.7 / 32) * 100 * self.figsize[1] ab.IP("title fontsize guess: {:.2f}".format(good_val)) self.plt_title_FS = good_val
def guess_appropriate_figsize(self, min_width=3.5): """Use fontsize and number of rows stacked in y-dir to figure out what a good overall height. Basically, we want the fontsize on the yticks to be just a bit less than the col width. The factor of 0.7 comes from practical experience with about the fraction of the height taken up by the plot in the vertical direction when things are fine. Re. width: make plot approx. square if no cbar is used; add on about 20% extra width if a cbar is used. We now put a floor on the width; anything less than 3.5 in seems pointless. """ ### "actual" formula, but bc matplotlib fontsize uses PPI, not ### DPI, then the DPI factors cancel! #num = self.plt_yticks_N * 1.2*self.plt_yticks_FS * (self.dpi / 72.) #den = 0.7 * self.dpi #height = num / den ### here, the factor of 2 includes the 'fudge factor' on row ### height and the denominator factor of 0.7, as well as a ### bit extra padding height = 2 * self.plt_yticks_N * self.plt_yticks_FS / 72. width = self.calc_fig_w_from_h(height) if width < min_width: ab.IP("Invoke min width: {}".format(min_width)) width = min_width height = self.calc_fig_h_from_w(width) ab.IP("figsize (h, w) guess (in): {:.2f}, {:.2f}" "".format(height, width)) self.figsize = (width, height)
def add_mat2d(self, Mobj, idx_pos=None, ext=None): """Mobj : is a mat2d object, which can have str labels. idx_pos : can be an index position (zerobase counting, of course!) for inserting the current obj in the list of things. NB: again, it is the allmat_labs that controls the order of mat2d obj. Behaves as list.insert(idx_pos, SOMETHING) would. This function adds to and updates the list of mat2d information in the current file_grid_netcc obj, as well as updating header and table (table_mat) info. """ # the output here contains info about whether a file_* obj # exists already with mat2ds in it OK_TO_GO = self.check_new_mat2d_with_current(Mobj) # this will insert it at the end, if no position has been # specified if idx_pos == None: idx_pos = self.nmat self.allmat_labs.insert(idx_pos, Mobj.label) self.allmat[Mobj.label] = Mobj self.nmat += 1 ab.IP("Inserted mat '{}' into index position [{}]" "".format(Mobj.label, idx_pos)) if OK_TO_GO == 1: self.nroi = Mobj.ncol self.roi_intvals = copy.deepcopy(Mobj.col_intvals) if Mobj.col_strlabs: self.has_strlabs = True self.roi_strlabs = copy.deepcopy(Mobj.col_strlabs) if ext == None: if Mobj.ext: self.ext = Mobj.ext else: self.ext = 'amat' else: self.ext = ext # update table+header self.make_header_GoN() self.make_table_mat_GoN()
def write_to_file_GoN(self, fname=''): """Write current information to a file on disk. fname can be provided here (gets precedence), or have been provided and stored in the obj previously. """ full_out = self.make_full_out_str_GoN() if fname: ooo = fname elif self.file_out: ooo = self.file_out else: ab.EP("Don't have an output name for this file-- can't write") fff = open(ooo, 'w') fff.write(full_out) fff.close() ab.IP("Wrote {} file: {}".format(self.ext, ooo))
def guess_appropriate_cbar_fontsize(self): """Similar goal/premise as guess_appropriate_figsize(). This if for the cbar values. Assumes the fig height is known at this point (so would have to be calc'ed after guess_appropriate_figsize(), potentially. """ ### some other ideas that didn't end up getting used... #n_pix_fig_y = self.dpi * self.figsize[1] #n_cbar_vals = self.cbar_n_interval+1 #n_pix_cbar_yticks = self.plt_yticks_FS * n_cbar_vals #n_pix_cbar_yticks*= (self.dpi / 72.) #guess1 = 0.8 * self.plt_yticks_FS good_val = 2 + (0.7 / 32) * 100 * self.figsize[1] ab.IP("cbar fontsize guess: {:.2f}".format(good_val)) self.cbar_FS = good_val
def set_mat_dims(self, allow_ragged=False): '''Set ncol and nrol of mat in this object. If a ragged matrix is detected, fail by default (or zeropad, if user wants) ''' if not (self.mat): ab.EP("Can't check dimensions of empty mat") #nc, nrmin, nrmax, is_rag, is_sq \ # = UTIL.mat_col_minrow_maxrow_ragged_square(self.mat) nr, ncmin, ncmax, is_rag, is_sq \ = UTIL.mat_row_mincol_maxcol_ragged_square(self.mat) self.nrow = nr if is_rag: if allow_ragged: ab.WP("ragged matrix: min = {}, max = {}\n" "-> am zeropadding".format(ncmin, ncmax)) for ii in range(self.nrow): diff = ncmax - len(self.mat[ii]) if diff: for jj in range(diff): self.mat[ii].append(0) else: ab.EP("ragged matrix: min = {}, max = {}\n" "no flag to allow ragged mats".format(ncmin, ncmax)) self.ncol = ncmax self.nelements = self.nrow * self.ncol ab.IP("mat dims (nrow, ncol): {}, {}".format(self.nrow, self.ncol))
# [PT] debug/test # ########################################################################## import sys, os, copy from afnipy import afni_base as ab from afnipy import afni_util as UTIL from afnipy import lib_cdiflist as LCDI # ============================================================================= if __name__ == "__main__": iopts = LCDI.parse_args(sys.argv) ab.IP("ver : {} (libver : {})" "".format(ver, LCDI.ver)) # read in inputs ngrad, cdiflist_list = LCDI.read_in_cdiflist(iopts.cdiflist) # calc bvals and (unscaled) bvecs list_bval, list_bvec \ = LCDI.cdiflist_vals_to_grad_bval( cdiflist_list, bval=iopts.bval_max ) # write outputs LCDI.write_files_from_bval_bvec(list_bval, list_bvec, iopts.prefix) sys.exit(0)
def make_plot(self): """ Construct the plot obj """ if not (self.figsize): # if one isn't entered, we'll try to *guess* a good one, # based on fontsize, number of cols, etc. and whether # there is a cbar self.guess_appropriate_figsize() if not (self.cbar_FS): self.guess_appropriate_cbar_fontsize() if not (self.plt_title_FS): self.guess_appropriate_title_fontsize() fig = plt.figure(figsize=self.figsize, dpi=self.dpi, facecolor=self.facecolor) subb = plt.subplot(111) ax = plt.gca() box = ax.get_position() IM = ax.imshow(self.m.mat, interpolation=self.interp, aspect=self.aspect, vmin=self.vmin, vmax=self.vmax, cmap=self.cbar) if self.plt_xticks_ON: plt.xticks(self.plt_xticks_ticks, self.plt_xticks_labels, rotation=self.plt_xticks_rot, ha=self.plt_xticks_ha, fontsize=self.plt_xticks_FS) else: plt.tick_params(axis='x', which='both', bottom=False, top=False, labelbottom=False) if self.plt_yticks_ON: plt.yticks(self.plt_yticks_ticks, self.plt_yticks_labels, rotation=self.plt_yticks_rot, fontsize=self.plt_yticks_FS) else: plt.tick_params(axis='y', which='both', left=False, right=False, labelleft=False) # this is do deal with an apparent bug in some versions of # matplotlib: # https://github.com/matplotlib/matplotlib/issues/14751 ax.set_ylim(self.plt_yticks_N - 0.5, -0.5) plt.title(self.plt_title_txt, fontsize=self.plt_title_FS) if self.do_show_cbar: cbar_wid = "{}%".format(self.cbar_width_perc) divider = make_axes_locatable(ax) TheCax = divider.append_axes(self.cbar_loc, size=cbar_wid, pad=self.cbar_pad) ntick = self.cbar_n_interval + 1 del_cbar = (self.vmax - self.vmin) / self.cbar_n_interval ColBar = [(self.vmin + del_cbar * ii) for ii in range(ntick)] if self.cbar_num_form: cbar_num_form = self.cbar_num_form elif ab.list_count_float_not_int(ColBar): # looks like floats max_cbar = max(ColBar) if max_cbar < 0.01: cbar_num_form = '%.2e' elif max_cbar < 10: cbar_num_form = '%.3f' elif max_cbar < 1000: cbar_num_form = '%.1f' else: cbar_num_form = '%.2e' else: # looks like ints max_cbar = max(ColBar) if max_cbar < 1000: cbar_num_form = '%d' else: cbar_num_form = '%.2e' cbar = plt.colorbar(IM, cax=TheCax, ticks=ColBar, format=cbar_num_form) cbar.ax.tick_params(labelsize=self.cbar_FS) if self.do_tight_layout: plt.tight_layout() else: subb.set_position([ box.x0 + box.width * 0.0, box.y0 + box.height * 0.05, box.width * 0.95, box.height * 0.95 ]) # ------------ save ----------- plt.savefig(self.file_out, dpi=self.dpi) ab.IP("Made plot: {}".format(self.file_out)) # ------------ display ------------- if self.do_hold_image: plt.ion() plt.show() try: input() except: raw_input()
# ########################################################################## import sys, os, copy from afnipy import afni_base as ab from afnipy import lib_mat2d_base as lm2b from afnipy import lib_mat2d_plot as lm2p # ============================================================================= if __name__ == "__main__": iopts = lm2p.parse_args_mat_plot(sys.argv) ab.IP("ver : {} (libver : {})" "".format(ver, lm2p.ver)) # create main object with matrix info M = lm2b.file_grid_netcc(iopts.input) # Make masterlist of parameters to plot if not (iopts.pars_list): list_of_pars = copy.deepcopy(M.allmat_labs) else: list_of_pars = [] for p in iopts.pars_list: if M.allmat_labs.__contains__(p): list_of_pars.append(p) else: ab.WP("Parameter '{}' does not exist in {}; " "continuing with others"