def cfgfile_to_dict(cfgfile): """ Reads cfgfile (in almasimmos format with optional pad numbers as comments) and returns a dictionary with 'x', 'y', 'z', and 'pad' columns. """ """ A module for plotting ASCII or AIPS++/CASA tables using CASA. Use: From casapy, # Preferred execfile 'tabplotter.py' example: # Set btb to be a tb tool filled with the contents of # ./cfgres_10to20.csv. The contents will be # fetched from ./cfgres_10to20.tb if it already # exists, and ./cfgres_10to20.csv otherwise. btb = filetotable('cfgres_10to20.csv') # Normal tb commands work. btb.browse() # You may need btb.clearlocks() btb.colnames() # As does help. help simpleplot # Plot everything in btb except the first column vs. the first column, # with a logarithmic y axis. simpleplot(btb, plotfunc=pl.semilogy) # Plot Nom.rms.res vs. Actual_res. simpleplot(btb, 'Nom.rms.res', 'Actual_res') # Plot Nom.rms.res and Actual_res vs. Nom.avg.res simpleplot(btb, ['Nom.rms.res', 'Actual_res'], 'Nom.avg.res') # timeaxis() is just a helper function now, but Gene DuVall might # extend it to use minutes, hours, etc., and/or to supply a time axis # for customized plots. # tablename() returns the table's filename without any directory or # .csv. """ __version__ = 0.02 __author__ = "Rob Reid, rreid@nrao.edu, starting from an example by D. Shepherd" import os, pl, re def uniquify_strlist(duplist): """Goes through the list of strings duplist, and appends a count number to any duplicates. i.e. given ['a', 'b', 'c', 'a', 'c', 'd', 'a', 'e'], it returns ['a_0', 'b', 'c_0', 'a_1', 'c_1', 'd', 'a_2', 'e']. Note that ['a', 'a', 'a_0'] would go to ['a_0', 'a_1', 'a_0']. If you have a list like that, you could run uniquify_strlist on the result. """ strlist = duplist[:] # Make a copy and leave duplist alone. strdict = {} for i in range(len(strlist)): s = strlist[i] if s in strdict: strdict[s].append(i) else: strdict[s] = [i] for s in strdict: if len(strdict[s]) > 1: for j in range(len(strdict[s])): strlist[strdict[s][j]] += "_%d" % j strdict[s] = [] return strlist def filetotable(fn, overwrite=False): """ Returns a CASA table (tb) tool as read from the comma separated value (CSV) file fn. Built around the fromascii line by Debra Shepherd. The first row in the CSV is assumed to be, and used as, column names, not as data values. If you want to use the tb for plotting, all other rows should be numbers. I usually produce my tables with whitespace separation for readability, but they can be easily converted to CSV format with this bash alias: # Use: csvize < table.readable > table.csv alias csvize='perl -wp -e "s/[ \t]+/,/g"' csvize will silently FAIL if there are any commas in table.readable! """ tbname = fn.replace('.csv', '') # Do it this way instead of one tbname += '.tb' # replace in case fn doesn't end # in .txt. mytb = tbtool.create() # tb is persistently global! if os.path.exists(tbname) and not overwrite: mytb.open(tbname) return mytb ## Fill (load) the data into CASA. # autoheader=True instructs mytb to create its own headers # (called Column1, Column2, etc) because the headers cannot be # interpreted. mytb.fromascii(tablename = tbname, asciifile = fn, sep=',', autoheader = True, nomodify = false) mytb.close() # Probably NOT modifiable now. mytb.open(tbname, nomodify=false) # Yes, I want to modify it! # The first row is column names. Move it elsewhere. boringcns = mytb.colnames() # Column1, Column2, ... # CASA doesn't like column names with spaces. colnames = [mytb.getcell(bcn, 0).replace(' ', '_') for bcn in boringcns] # This isn't just paranoia. colnames = uniquify_strlist(colnames) mytb.removerows([0]) for (bcn, ncn) in zip(boringcns, colnames): mytb.renamecol(bcn, ncn) mytb.flush() return mytb def timeaxis(datatb): """ Attempts to return a reasonable time axis and label for it from datatb. """ sec = datatb.getcol('Seconds').astype(float) t = sec # REMOVE when things get smarter! tlabel = "Time (s)" tint = sec[-1] - sec[0] if tint < 300.0: t = sec # Leave it in seconds tlabel = "Time (s)" return t, tlabel def tablename(datatb): """ Returns a slightly cleaned up name for datatb. """ tablab = datatb.name() tablab = re.sub(r"^.*/", '', tablab) tablab = re.sub(r"\.tb", '', tablab) return tablab def simpleplot(datatb, ycolnames=[], xcolname='', colnames=[], plotfunc=pl.plot): """ Graph datatb[ycolname] vs. datatb[xcolname] for each ycolname in ycolnames, on the same plot. xcolname defaults to the first column in colnames or datatb.colnames(). ycolnames defaults to all but xcolname in colnames or datatb.colnames(). """ # clear plotter pl.clf() # turn interactive mode ON (allows automatic updates of plots) pl.ion() # Handle defaults. if len(colnames) == 0: colnames = datatb.colnames() if len(xcolname) == 0: xcolname = colnames[0] if len(ycolnames) == 0: ycolnames = colnames[:] ycolnames.remove(xcolname) x = datatb.getcol(xcolname) if isinstance(ycolnames, str): y = datatb.getcol(ycolnames) plotfunc(x, y) pl.ylabel(ycolnames) elif len(ycolnames) == 1: y = datatb.getcol(ycolnames[0]) plotfunc(x, y) pl.ylabel(ycolnames[0]) else: for ycolname in ycolnames: y = datatb.getcol(ycolname) plotfunc(x, y, label = ycolname) pl.legend(loc='best') pl.xlabel(xcolname) pl.title(tablename(datatb))