def run_peakfit(dg, config, db_ecal): """ """ print('\nRunning peakfit ...') # do the analysis gb = dg.fileDB.groupby(config['gb_cols']) gb_args = [config, db_ecal] result = gb.apply(peakfit_group, *gb_args) # write the results if config['write_db']: # write separate tables for each energy estimator to the TinyDB for epar in config['rawe']: # format output epar_cols = [r for r in result.columns if epar in r] df_epar = result[epar_cols].copy() df_epar.rename(columns={c: c.split('_')[-1] for c in epar_cols}, inplace=True) df_epar['tsgen'] = int(time.time()) df_epar.reset_index(inplace=True) df_epar['run'] = df_epar['run'].astype(str) # write the DataFrame to JSON TinyDB table = db_ecal.table(f'peakfit_{epar}') query = db.Query() for i, row in df_epar.iterrows(): table.upsert(row.to_dict(), query['run'] == row['run']) # show in-memory state and then write to file pprint(db_ecal.storage.read()) pmd.write_pretty(db_ecal.storage.read(), config['ecaldb'])
def init_ecaldb(config): """ one-time set up of primary database file """ ans = input('(Re)create main ecal JSON file? Are you really sure? (y/n) ') if ans.lower() != 'y': exit() f_db = config['ecaldb'] # for pgt, should have one for each detector if os.path.exists(f_db): os.remove(f_db) # create the database in-memory db_ecal = db.TinyDB(storage=MemoryStorage) query = db.Query() # create a table with metadata (provenance) about this calibration file file_info = { "system": config['system'], "cal_type": "energy", "created_gmt": datetime.utcnow().strftime("%m/%d/%Y, %H:%M:%S"), "input_table": config['input_table'] } db_ecal.table('_file_info').insert(file_info) # pretty-print the JSON database to file raw_db = db_ecal.storage.read() pmd.write_pretty(raw_db, f_db) # show the file as-is on disk with open(f_db) as f: print(f.read())
def run_peakfit(dg, config, db_ecal): """ $ ./energy_cal.py -q 'query' -pf [-pi KEY] [-p : show plot] Using the first guess calibration from peakdet, fit each peak of interest and compute the calibration and resolution curves. """ gb = dg.fileDB.groupby(config['gb_cols']) runs = dg.fileDB.run.unique() cyclo, cychi = dg.fileDB.cycle.iloc[0], dg.fileDB.cycle.iloc[-1] print(f'Running peakfit, runs {runs}, cycles {cyclo}--{cychi}') result = gb.apply(peakfit, *[config, db_ecal]) def parse_results(df_run): """ for each run, compute entries for each energy estimator for TinyDB """ run = int(df_run.index[0]) for epar in config['rawe']: # format output epar_cols = [r for r in df_run.columns if epar in r] df_epar = df_run[epar_cols].copy() df_epar.rename(columns={c: c.split('_')[-1] for c in epar_cols}, inplace=True) df_epar.reset_index(inplace=True) if 'cycle' in df_epar.columns: # this is redundant with cyclo and cychi df_epar.drop('cycle', 1, inplace=True) cyclo, cychi = df_epar.iloc[0][['cyclo', 'cychi']] tb_name = f'peakfit_{epar}' print('Results:', tb_name) print(f'Run {run} cycles {cyclo}--{cychi}') print(df_epar) # this is in-memory, no write to file yet table = db_ecal.table(tb_name) q = db.Query() for i, row in df_epar.iterrows(): que = ((q.run == row.run) & (q.cyclo == row.cyclo) & (q.cychi == row.cychi)) table.upsert(row.to_dict(), que) # parse the results result.groupby(['run']).apply(parse_results) if not config['write_db']: print('Done. ecalDB write mode not set (-w option)') return # show in-memory state and then write to file # pprint(db_ecal.storage.read()) print('Writing results to ecalDB.') pmd.write_pretty(db_ecal.storage.read(), config['ecaldb'])
def run_peakdet(dg, config, db_ecal): """ $ ./energy_cal.py -q 'query' -p1 [-p : show plot] Run "first guess" calibration of an arbitrary energy estimator. NOTE: if you use too high a peakdet threshold, you may not capture all the lines you're looking for. If it's too low, then you have to deal with more lines than you probably want for this 1-pt calibration. We include an option to show a diagnostic plot for this reason. """ print('\nRunning peakdet ...') # do the analysis gb = dg.fileDB.groupby(config['gb_cols']) gb_args = [config] run_no = np.array(dg.fileDB['run'])[0] print(f'Running peakdet for run: {run_no}') result = gb.apply(peakdet_group, *gb_args) # write the results if config['write_db']: # write separate tables for each energy estimator to the TinyDB for epar in config['rawe']: # format output epar_cols = [r for r in result.columns if epar in r] df_epar = result[epar_cols].copy() df_epar.rename(columns={c: c.split('_')[-1] for c in epar_cols}, inplace=True) df_epar['tsgen'] = int(time.time()) df_epar.reset_index(inplace=True) df_epar['run'] = df_epar['run'].astype(str) # write the DataFrame to JSON TinyDB table = db_ecal.table(f'peakdet_{epar}') query = db.Query() for i, row in df_epar.iterrows(): table.upsert(row.to_dict(), query['run'] == row['run']) # show in-memory state and then write to file pprint(db_ecal.storage.read()) pmd.write_pretty(db_ecal.storage.read(), config['ecaldb'])
def run_peakdet(dg, config, db_ecal): """ $ ./energy_cal.py -q 'query' [-pd / -pi inp_id] [-p : show plot] [-w : write ecalDB] Run "first guess" calibration of a list of energy parameters. Creates a table in the ecalDB for each one, storing up to 2nd order polynomials: y = p0 + p1 * x + p2 * x**2. These are used as inputs to "peakfit". We have two modes: -- automatic (default): find p1 by matching the ratios of uncalibrated auto-detected peaks to an input list of peaks in keV. Assumes y = p1 * x, which may not always work for all detectors. -- "input peaks": use a JSON config file to set expected peak locations. This is useful when the spectrum deviates too much from y = p1 * x. Files are grouped by run, and optionally by cycle (calibrates individual files within the run.) Right now, we require the first item in gb_cols to be 'run'. It's also possible to group a subset of files in a run together, with a query like "run==123 and cycle > 456" We then write several TinyDB 'Tables' to our ecalDB file. They have a nice 1--1 correspondence to pandas dataframes. """ gb = dg.fileDB.groupby(config['gb_cols']) runs = dg.fileDB.run.unique() cyclo, cychi = dg.fileDB.cycle.iloc[0], dg.fileDB.cycle.iloc[-1] print(f'Running peakdet, runs {runs}, cycles {cyclo}--{cychi}') # run peakdet function as a pandas groupby if 'input_id' in config.keys(): pol = config['pol'][0] print(f'Fitting manually input peak locations to polynomial, order', pol) result = gb.apply(peakdet_input, *[config]) else: print('Automatically detecting peaks based on input list.') result = gb.apply(peakdet_auto, *[config]) def parse_results(df_run): """ for each run, compute entries for each energy estimator to TinyDB """ run = int(df_run.index[0]) for epar in config['rawe']: # format output table epar_cols = [r for r in df_run.columns if epar in r] df_epar = df_run[epar_cols].copy() df_epar.rename(columns={c: c.split('_')[-1] for c in epar_cols}, inplace=True) df_epar['calpass'] = df_epar['calpass'].astype(int) df_epar.reset_index(inplace=True) if 'cycle' in df_epar.columns: # this is redundant with cyclo and cychi df_epar.drop('cycle', 1, inplace=True) cyclo, cychi = df_epar.iloc[0][['cyclo', 'cychi']] tb_name = f'peakinp_{epar}' if 'input_id' in config.keys( ) else f'peakdet_{epar}' print('Results:', tb_name) print(f'Run {run} cycles {cyclo}--{cychi}') print(df_epar) # this is in-memory, no write to file yet table = db_ecal.table(tb_name) q = db.Query() for i, row in df_epar.iterrows(): que = ((q.run == row.run) & (q.cyclo == row.cyclo) & (q.cychi == row.cychi)) table.upsert(row.to_dict(), que) # parse the results result.groupby(['run']).apply(parse_results) if not config['write_db']: print('Done. ecalDB write mode not set (-w option)') return # show in-memory state and then write to file # pprint(db_ecal.storage.read()) print('Writing results to ecalDB.') pmd.write_pretty(db_ecal.storage.read(), config['ecaldb'])