Skip to content
Snippets Groups Projects
Commit 08f03ccf authored by ferrari's avatar ferrari
Browse files

Add script for bombyx ipi labelling

parent e71078b3
No related branches found
No related tags found
No related merge requests found
import ipi_extract as ipi
import pandas as pd
import argparse
import numpy as np
import os
import matplotlib.pyplot as plt
from functools import partial
from matplotlib.widgets import Button
import sys
class BetterIter(object):
def __init__(self, to_wrap):
self.wrapped = iter(to_wrap)
self.max_num = len(to_wrap)
self.to_wrap = to_wrap
self.overlap = False
def __iter__(self):
return self
def _test_done(self ,list_pass):
self.overlap = len(list_pass) >= self.max_num
def __next__(self):
while True:
try:
val = next(self.wrapped)
except StopIteration:
self.wrapped = iter(self.to_wrap)
val = next(self.wrapped)
self.done_file.seek(0)
list_pass = [int(v) for v in self.done_file.read().split('\n') if len(v)]
self._test_done(list_pass)
if (val not in list_pass) or self.overlap:
break
self.current = val
return val
def _next_file(event, refs, order, df, save, args, outpath, done_file):
tmp = pd.DataFrame.from_dict(refs['callback'].df, orient='index')
ind = order.current
tmp['file'] = df.iloc[ind].filepredmax
tmp['passage'] = df.iloc[ind].ipassage
tmp['nb_ind'] = df.iloc[ind].nbindiv
tmp['pred_max'] = df.iloc[ind].predmax
tmp['annotator'] = args.annotator
save.append(tmp)
df_ann = pd.concat(save)
df_ann.to_hdf(outpath, 'df')
if len(tmp):
done_file.write(f'{df.iloc[ind].ipassage}\n')
done_file.flush()
ind = order.__next__()
try:
ipi.reset(refs['callback'], os.path.join(args.wd, df.iloc[ind].filepredmax.strip('/')), args.channel)
refs['fig'].canvas.set_window_title('IPI of ' + df.iloc[ind].filepredmax.rsplit('/', 1)[-1])
except (RuntimeError,FileNotFoundError) as e:
print(e, 'Opening next file')
_next_file(event, refs, order, df, save, args, outpath, done_file)
def main(args):
if args.out == '':
outpath = args.input.rsplit('.', 1)[0] + f'_{args.annotator}.h5'
else:
outpath = args.out
save = []
if os.path.isfile(outpath) and not args.erase:
save.append(pd.read_hdf(outpath))
df = pd.read_pickle(args.input)
done_file = open(args.done_file, 'a+')
done_file.seek(0)
file_list = [int(v) for v in done_file.read().split('\n') if len(v)]
df = df[~df.ipassage.isin(file_list)]
overlap = False
if not len(df):
df = pd.read_pickle(args.input)
overlap = True
if args.nb_ind != -1:
df = df[df.nbindiv <= args.nb_ind]
samples_order = BetterIter(np.random.choice(len(df), len(df), replace=False))
samples_order.done_file = done_file
samples_order.overlap = overlap
ind = samples_order.__next__()
try:
ref_dict = ipi.init(os.path.join(args.wd, df.iloc[ind].filepredmax.strip('/')), args.channel)
except(RuntimeError,FileNotFoundError) as e:
print(e, 'Opening next file')
ind = samples_order.__next__()
ref_dict = ipi.init(os.path.join(args.wd, df.iloc[ind].filepredmax.strip('/')), args.channel)
next_file = partial(_next_file, refs=ref_dict, order=samples_order, df=df, save=save, args=args, outpath=outpath,
done_file=done_file)
next_ax = plt.subplot(ref_dict['gridspec'][-1, -2:])
next_button = Button(next_ax, 'Next file')
next_button.on_clicked(next_file)
plt.draw()
plt.pause(0.2)
ref_dict['fig'].set_constrained_layout(False)
plt.show()
tmp = pd.DataFrame.from_dict(ref_dict['callback'].df, orient='index')
ind = samples_order.current
tmp['file'] = df.iloc[ind].filepredmax
tmp['passage'] = df.iloc[ind].ipassage
tmp['nb_ind'] = df.iloc[ind].nbindiv
tmp['pred_max'] = df.iloc[ind].predmax
save.append(tmp)
df_ann = pd.concat(save)
df_ann['annotator'] = args.annotator
df_ann.to_hdf(outpath, 'df')
done_file.close()
return 0
if __name__ == '__main__':
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument("input", type=str, help="Input metadata file")
parser.add_argument("annotator", type=str, help="Your name")
parser.add_argument("--out", type=str, default='', help="Output file. Default to the input_path'.annotator.h5'")
parser.add_argument("--channel", type=int, default=0, help="Sound channel to be analysed. Indices start from 0.")
parser.add_argument("--nb_ind", type=int, default=1, help="Maximum number of individual for each track. -1 for no limit")
parser.add_argument("--erase", action='store_true', help="If out file exist and this option is not given,"
" the computation will be halted")
parser.add_argument("--wd", type=str, default='/nfs/NASDELL/SABIOD/SITE/BOMBYX/', help='Path to root dir'
' containing Bombyx files')
parser.add_argument("--done_file", type=str,
default='/nfs/NASDELL/SABIOD/SITE/BOMBYX/manip_2021/IPI_scripts/done_file.csv',
help='Path to file listing files done')
args = parser.parse_args()
sys.exit(main(args))
\ No newline at end of file
......@@ -5,8 +5,7 @@ import scipy.signal as sg
import soundfile as sf
import os
import sys
from matplotlib.widgets import Button, Cursor, MultiCursor, CheckButtons, RadioButtons, AxesWidget, TextBox
from matplotlib.patches import Circle
from matplotlib.widgets import Button, Cursor, RadioButtons, AxesWidget
from fractions import Fraction
from pydub import AudioSegment
from pydub.playback import play
......@@ -422,9 +421,21 @@ class Callback(object):
self.view_ax[ind][2].set_xlabel(f'Corr man:{dic["ipi_corr_man"]:.3f} auto:{dic["ipi_corr_auto"]:.3f}')
self.view_ax[ind][3].set_xlabel(f'Ceps man:{dic["ipi_ceps_man"]:.3f} auto:{dic["ipi_ceps_auto"]:.3f}')
def _set_visible(self, ind=None, state=False):
if ind is None:
ind = self.curr
self.view_data[ind][0][1][0].set_visible(state)
self.view_data[ind][0][1][1].set_visible(state)
self.view_data[ind][1][1][0].set_visible(state)
self.view_data[ind][1][1][1].set_visible(state)
self.view_data[ind][2][1].set_visible(state)
self.view_data[ind][3][1].set_visible(state)
def reset_curr(self, event):
self.df[self.offset[self.curr_ind[self.curr], 0]] = EMLN.copy()
self._set_label()
self._set_visible()
plt.draw()
def reset(self, song, sr, song_resample):
......@@ -439,8 +450,11 @@ class Callback(object):
self.scat.set_offsets(self.offset)
self.curr_ind = 3 * [None] # Ind of click for each plot
self.curr_vert = 3 * [0] # Current vertical line of sig/spec for each plot
for i in range(3):
self.view_data[i][1][0].set_clim(2000,2100)
for i in range(3):
self._set_label(i, EMLN)
self._set_visible(i)
plt.draw()
......@@ -526,8 +540,9 @@ def init(in_path, channel, low=2e3, high=20e3):
data_view[i][0][1][0].set_visible(False)
data_view[i][0][1][1].set_visible(False)
data_view[i][1][0] = ax_view[i][1].specgram(np.random.normal(0, 1, int(20e-3 * sr)),
data_view[i][1][0] = ax_view[i][1].specgram(np.random.normal(0, 1e-6, int(20e-3 * sr)),
Fs=sr, NFFT=128, noverlap=127, cmap='jet')[-1]
data_view[i][1][0].set_clim(2000,2100)
data_view[i][1][1] = (ax_view[i][1].axvline(0.01, c='k', linestyle='--'), ax_view[i][1].axvline(0.01, c='k'))
data_view[i][1][1][0].set_visible(False)
data_view[i][1][1][1].set_visible(False)
......@@ -560,10 +575,7 @@ def init(in_path, channel, low=2e3, high=20e3):
m_cursor[i].linev[0].set_linestyle('--')
m_cursor[i].linev[1].set_linestyle('--')
callback.view_data = data_view
plt.draw()
plt.pause(0.2)
fig.set_constrained_layout(False)
return {'callback': callback, 'fig': fig, 'buttons':
return {'callback': callback, 'fig': fig, 'gridspec': gs, 'buttons':
{'b_left': b_left, 'b_right': b_right, 'play_b': play_b, 'resize_b': resize_b, 'r_button': r_button,
'fs_click': cid, 'reset_b': reset_b}} # Needed to keep the callbacks alive
......@@ -582,6 +594,9 @@ def main(args):
print(f'Out file {outpath} already exist and erase option isn\'t set.')
return 1
ref_dict = init(args.input, args.channel)
plt.draw()
plt.pause(0.2)
ref_dict['fig'].set_constrained_layout(False)
plt.show()
df = pd.DataFrame.from_dict(ref_dict['callback'].df, orient='index')
df.to_hdf(outpath, 'df')
......@@ -593,7 +608,7 @@ if __name__ == '__main__':
class ArgumentParser(argparse.ArgumentParser):
def error(self, message):
if message.startswith('the following arguments are required:'):
raise ValueError()
raise ValueError(message)
super(ArgumentParser, self).error(message)
parser = ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment