diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..b889e93
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+*.pyc
+*.ipynb*
+training/.flag*
+prediction*.csv
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..a50d135
--- /dev/null
+++ b/README.md
@@ -0,0 +1,66 @@
+# Dependencies
+
+Ubuntu 14.04, python 2.7, CUDA 8.0, cudnn 5.1, h5py (2.6.0), SimpleITK (0.10.0), numpy (1.11.3), nvidia-ml-py (7.352.0), matplotlib (2.0.0), scikit-image (0.12.3), scipy (0.18.1), pyparsing (2.1.4), pytorch (0.1.10+ac9245a) (anaconda is recommended)
+
+This is my configuration, I am not sure about the compatability of other versions
+
+
+
+# Instructions for runing
+
+Testing
+1. unzip the stage 2 data
+2. go to root folder
+3. open config_submit.py, filling in datapath with the stage 2 data path
+4. python main.py
+5. get the results from prediction.csv
+
+if you have bug about short of memory, set the 'n_worker_preprocessing' in config\_submit.py to a int that is smaller than your core number.
+
+Training
+1. Install all dependencies
+2. Prepare stage1 data, LUNA data, and LUNA segment results (https://luna16.grand-challenge.org/download/), unzip them to separate folders
+3. Go to ./training and open config_training.py
+4. Filling in stage1_data_path, luna_raw, luna_segment with the path mentioned above
+5. Filling in luna_data, preprocess_result_path, with tmp folders
+6. bash run_training.sh and wait for the finishing of training (it may take several days)
+
+If you do not have 8 GPUs or your the memory of your GPUs is less than 12 GB, decrease the number of -b and -b2 in run\_training.sh, and modify the 'CUDA\_VISIBLE\_DEVICES=0,1,..,n\_your\_gpu'. The time of training is very long (3~4 days with 8 TITANX).
+
+
+
+# Brief Introduction to algorithm
+Extra Data and labels: we use LUNA16 as extra data, and we manually labeled the locations of nodules in the stage1 training dataset. We also manually washed the label of LUNA16, deleting those that we think irrelavent to cancer. The labels are stored in ./training./detector./labels.
+
+The training involves four steps
+1. prepare data
+
+ All data are resized to 1x1x1 mm, the luminance is clipped between -1200 and 600, scaled to 0-255 and converted to uint8. A mask that include the lungs is calculated, luminance of every pixel outside the mask is set to 170. The results will be stored in 'preprocess_result_path' defined in config_training.py along with their corresponding detection labels.
+
+2. training a nodule detector
+
+ in this part, a 3d faster-rcnn is used as the detector. The input size is 128 x 128 x 128, an online hard negative sample mining method is used. The network structure is based on U-net.
+
+3. get all proposals
+
+ The model trained in part 2 was tested on all data, giving all suspicious nodule locations and confidences (proposals)
+
+4. training a cancer classifier
+
+ For each case, 5 proposals are samples according to its confidence, and for each proposal a 96 x 96 x 96 cubes centered at the proposal center is cropped.
+
+ These proposals are fed to the detector and the feature in the last convolutional layer is extracted for each proposal. These features are fed to a fully-connected network and a cancer probability $P_i$ is calculated for each proposal. The cancer probability for this case is calculated as:
+
+ $P = 1-(1-P_d)\Pi(1-P_i)$,
+
+ where the $P_d$ stand for the probability of cancer of a dummy nodule, which is a trainable constant. It account for any possibility that the nodule is missed by the detector or this patient do not have a nodule now. Then the classification loss is calculated as the cross entropy between this $P$ and the label.
+
+ The second loss term is defined as: $-\log(P)\boldsymbol{1}(y_{nod}=1 \& P<0.03)$, which means that if this proposal is manually labeled as nodule and its probability is lower than 3%, this nodule would be forced to have higher cancer probability. Yet the effect of this term has not been carefully studied.
+
+ To prevent overfitting, the network is alternatively trained on detection task and classification task.
+
+The network archetecture is shown below
+
+
+
+
diff --git a/bbox_result/.gitignore b/bbox_result/.gitignore
new file mode 100644
index 0000000..76bedae
--- /dev/null
+++ b/bbox_result/.gitignore
@@ -0,0 +1,5 @@
+# Ignore everything in this directory
+*
+# Except this file
+!.gitignore
+
diff --git a/config_submit.py b/config_submit.py
new file mode 100644
index 0000000..a8d8012
--- /dev/null
+++ b/config_submit.py
@@ -0,0 +1,13 @@
+config = {'datapath':'/work/DataBowl3/stage2/stage2/',
+ 'preprocess_result_path':'./prep_result/',
+ 'outputfile':'prediction.csv',
+
+ 'detector_model':'net_detector',
+ 'detector_param':'./model/detector.ckpt',
+ 'classifier_model':'net_classifier',
+ 'classifier_param':'./model/classifier.ckpt',
+ 'n_gpu':8,
+ 'n_worker_preprocessing':None,
+ 'use_exsiting_preprocessing':False,
+ 'skip_preprocessing':False,
+ 'skip_detect':False}
diff --git a/data_classifier.py b/data_classifier.py
new file mode 100644
index 0000000..58b0e73
--- /dev/null
+++ b/data_classifier.py
@@ -0,0 +1,219 @@
+import numpy as np
+import torch
+from torch.utils.data import Dataset
+import os
+import time
+import collections
+import random
+from layers import iou
+from scipy.ndimage import zoom
+import warnings
+from scipy.ndimage.interpolation import rotate
+from layers import nms,iou
+import pandas
+
+class DataBowl3Classifier(Dataset):
+ def __init__(self, split, config, phase = 'train'):
+ assert(phase == 'train' or phase == 'val' or phase == 'test')
+
+ self.random_sample = config['random_sample']
+ self.T = config['T']
+ self.topk = config['topk']
+ self.crop_size = config['crop_size']
+ self.stride = config['stride']
+ self.augtype = config['augtype']
+ self.filling_value = config['filling_value']
+
+ #self.labels = np.array(pandas.read_csv(config['labelfile']))
+
+ datadir = config['datadir']
+ bboxpath = config['bboxpath']
+ self.phase = phase
+ self.candidate_box = []
+ self.pbb_label = []
+
+ idcs = split
+ self.filenames = [os.path.join(datadir, '%s_clean.npy' % idx.split('-')[0]) for idx in idcs]
+ if self.phase!='test':
+ self.yset = 1-np.array([f.split('-')[1][2] for f in idcs]).astype('int')
+
+
+ for idx in idcs:
+ pbb = np.load(os.path.join(bboxpath,idx+'_pbb.npy'))
+ pbb = pbb[pbb[:,0]>config['conf_th']]
+ pbb = nms(pbb, config['nms_th'])
+
+ lbb = np.load(os.path.join(bboxpath,idx+'_lbb.npy'))
+ pbb_label = []
+
+ for p in pbb:
+ isnod = False
+ for l in lbb:
+ score = iou(p[1:5], l)
+ if score > config['detect_th']:
+ isnod = True
+ break
+ pbb_label.append(isnod)
+# if idx.startswith()
+ self.candidate_box.append(pbb)
+ self.pbb_label.append(np.array(pbb_label))
+ self.crop = simpleCrop(config,phase)
+
+
+ def __getitem__(self, idx,split=None):
+ t = time.time()
+ np.random.seed(int(str(t%1)[2:7]))#seed according to time
+
+ pbb = self.candidate_box[idx]
+ pbb_label = self.pbb_label[idx]
+ conf_list = pbb[:,0]
+ T = self.T
+ topk = self.topk
+ img = np.load(self.filenames[idx])
+ if self.random_sample and self.phase=='train':
+ chosenid = sample(conf_list,topk,T=T)
+ #chosenid = conf_list.argsort()[::-1][:topk]
+ else:
+ chosenid = conf_list.argsort()[::-1][:topk]
+ croplist = np.zeros([topk,1,self.crop_size[0],self.crop_size[1],self.crop_size[2]]).astype('float32')
+ coordlist = np.zeros([topk,3,self.crop_size[0]/self.stride,self.crop_size[1]/self.stride,self.crop_size[2]/self.stride]).astype('float32')
+ padmask = np.concatenate([np.ones(len(chosenid)),np.zeros(self.topk-len(chosenid))])
+ isnodlist = np.zeros([topk])
+
+
+ for i,id in enumerate(chosenid):
+ target = pbb[id,1:]
+ isnod = pbb_label[id]
+ crop,coord = self.crop(img,target)
+ if self.phase=='train':
+ crop,coord = augment(crop,coord,
+ ifflip=self.augtype['flip'],ifrotate=self.augtype['rotate'],
+ ifswap = self.augtype['swap'],filling_value = self.filling_value)
+ crop = crop.astype(np.float32)
+ croplist[i] = crop
+ coordlist[i] = coord
+ isnodlist[i] = isnod
+
+ if self.phase!='test':
+ y = np.array([self.yset[idx]])
+ return torch.from_numpy(croplist).float(), torch.from_numpy(coordlist).float(), torch.from_numpy(isnodlist).int(), torch.from_numpy(y)
+ else:
+ return torch.from_numpy(croplist).float(), torch.from_numpy(coordlist).float()
+ def __len__(self):
+ if self.phase != 'test':
+ return len(self.candidate_box)
+ else:
+ return len(self.candidate_box)
+
+
+
+class simpleCrop():
+ def __init__(self,config,phase):
+ self.crop_size = config['crop_size']
+ self.scaleLim = config['scaleLim']
+ self.radiusLim = config['radiusLim']
+ self.jitter_range = config['jitter_range']
+ self.isScale = config['augtype']['scale'] and phase=='train'
+ self.stride = config['stride']
+ self.filling_value = config['filling_value']
+ self.phase = phase
+
+ def __call__(self,imgs,target):
+ if self.isScale:
+ radiusLim = self.radiusLim
+ scaleLim = self.scaleLim
+ scaleRange = [np.min([np.max([(radiusLim[0]/target[3]),scaleLim[0]]),1])
+ ,np.max([np.min([(radiusLim[1]/target[3]),scaleLim[1]]),1])]
+ scale = np.random.rand()*(scaleRange[1]-scaleRange[0])+scaleRange[0]
+ crop_size = (np.array(self.crop_size).astype('float')/scale).astype('int')
+ else:
+ crop_size = np.array(self.crop_size).astype('int')
+ if self.phase=='train':
+ jitter_range = target[3]*self.jitter_range
+ jitter = (np.random.rand(3)-0.5)*jitter_range
+ else:
+ jitter = 0
+ start = (target[:3]- crop_size/2 + jitter).astype('int')
+ pad = [[0,0]]
+ for i in range(3):
+ if start[i]<0:
+ leftpad = -start[i]
+ start[i] = 0
+ else:
+ leftpad = 0
+ if start[i]+crop_size[i]>imgs.shape[i+1]:
+ rightpad = start[i]+crop_size[i]-imgs.shape[i+1]
+ else:
+ rightpad = 0
+ pad.append([leftpad,rightpad])
+ imgs = np.pad(imgs,pad,'constant',constant_values =self.filling_value)
+ crop = imgs[:,start[0]:start[0]+crop_size[0],start[1]:start[1]+crop_size[1],start[2]:start[2]+crop_size[2]]
+
+ normstart = np.array(start).astype('float32')/np.array(imgs.shape[1:])-0.5
+ normsize = np.array(crop_size).astype('float32')/np.array(imgs.shape[1:])
+ xx,yy,zz = np.meshgrid(np.linspace(normstart[0],normstart[0]+normsize[0],self.crop_size[0]/self.stride),
+ np.linspace(normstart[1],normstart[1]+normsize[1],self.crop_size[1]/self.stride),
+ np.linspace(normstart[2],normstart[2]+normsize[2],self.crop_size[2]/self.stride),indexing ='ij')
+ coord = np.concatenate([xx[np.newaxis,...], yy[np.newaxis,...],zz[np.newaxis,:]],0).astype('float32')
+
+ if self.isScale:
+ with warnings.catch_warnings():
+ warnings.simplefilter("ignore")
+ crop = zoom(crop,[1,scale,scale,scale],order=1)
+ newpad = self.crop_size[0]-crop.shape[1:][0]
+ if newpad<0:
+ crop = crop[:,:-newpad,:-newpad,:-newpad]
+ elif newpad>0:
+ pad2 = [[0,0],[0,newpad],[0,newpad],[0,newpad]]
+ crop = np.pad(crop,pad2,'constant',constant_values =self.filling_value)
+
+ return crop,coord
+
+def sample(conf,N,T=1):
+ if len(conf)>N:
+ target = range(len(conf))
+ chosen_list = []
+ for i in range(N):
+ chosenidx = sampleone(target,conf,T)
+ chosen_list.append(target[chosenidx])
+ target.pop(chosenidx)
+ conf = np.delete(conf, chosenidx)
+
+
+ return chosen_list
+ else:
+ return np.arange(len(conf))
+
+def sampleone(target,conf,T):
+ assert len(conf)>1
+ p = softmax(conf/T)
+ p = np.max([np.ones_like(p)*0.00001,p],axis=0)
+ p = p/np.sum(p)
+ return np.random.choice(np.arange(len(target)),size=1,replace = False, p=p)[0]
+
+def softmax(x):
+ maxx = np.max(x)
+ return np.exp(x-maxx)/np.sum(np.exp(x-maxx))
+
+
+def augment(sample, coord, ifflip = True, ifrotate=True, ifswap = True,filling_value=0):
+ # angle1 = np.random.rand()*180
+ if ifrotate:
+ validrot = False
+ counter = 0
+ angle1 = np.random.rand()*180
+ size = np.array(sample.shape[2:4]).astype('float')
+ rotmat = np.array([[np.cos(angle1/180*np.pi),-np.sin(angle1/180*np.pi)],[np.sin(angle1/180*np.pi),np.cos(angle1/180*np.pi)]])
+ sample = rotate(sample,angle1,axes=(2,3),reshape=False,cval=filling_value)
+
+ if ifswap:
+ if sample.shape[1]==sample.shape[2] and sample.shape[1]==sample.shape[3]:
+ axisorder = np.random.permutation(3)
+ sample = np.transpose(sample,np.concatenate([[0],axisorder+1]))
+ coord = np.transpose(coord,np.concatenate([[0],axisorder+1]))
+
+ if ifflip:
+ flipid = np.array([np.random.randint(2),np.random.randint(2),np.random.randint(2)])*2-1
+ sample = np.ascontiguousarray(sample[:,::flipid[0],::flipid[1],::flipid[2]])
+ coord = np.ascontiguousarray(coord[:,::flipid[0],::flipid[1],::flipid[2]])
+ return sample, coord
diff --git a/data_detector.py b/data_detector.py
new file mode 100644
index 0000000..35f0874
--- /dev/null
+++ b/data_detector.py
@@ -0,0 +1,417 @@
+import numpy as np
+import torch
+from torch.utils.data import Dataset
+import os
+import time
+import collections
+import random
+from layers import iou
+from scipy.ndimage import zoom
+import warnings
+from scipy.ndimage.interpolation import rotate
+from scipy.ndimage.morphology import binary_dilation,generate_binary_structure
+
+class DataBowl3Detector(Dataset):
+ def __init__(self, split, config, phase = 'train',split_comber=None):
+ assert(phase == 'train' or phase == 'val' or phase == 'test')
+ self.phase = phase
+ self.max_stride = config['max_stride']
+ self.stride = config['stride']
+ sizelim = config['sizelim']/config['reso']
+ sizelim2 = config['sizelim2']/config['reso']
+ sizelim3 = config['sizelim3']/config['reso']
+ self.blacklist = config['blacklist']
+ self.isScale = config['aug_scale']
+ self.r_rand = config['r_rand_crop']
+ self.augtype = config['augtype']
+ data_dir = config['datadir']
+ self.pad_value = config['pad_value']
+
+ self.split_comber = split_comber
+ idcs = split
+ if phase!='test':
+ idcs = [f for f in idcs if f not in self.blacklist]
+
+ self.channel = config['chanel']
+ if self.channel==2:
+ self.filenames = [os.path.join(data_dir, '%s_merge.npy' % idx) for idx in idcs]
+ elif self.channel ==1:
+ if 'cleanimg' in config and config['cleanimg']:
+ self.filenames = [os.path.join(data_dir, '%s_clean.npy' % idx) for idx in idcs]
+ else:
+ self.filenames = [os.path.join(data_dir, '%s_img.npy' % idx) for idx in idcs]
+ self.kagglenames = [f for f in self.filenames if len(f.split('/')[-1].split('_')[0])>20]
+ self.lunanames = [f for f in self.filenames if len(f.split('/')[-1].split('_')[0])<20]
+
+ labels = []
+
+ for idx in idcs:
+ if config['luna_raw'] ==True:
+ try:
+ l = np.load(os.path.join(data_dir, '%s_label_raw.npy' % idx))
+ except:
+ l = np.load(os.path.join(data_dir, '%s_label.npy' %idx))
+ else:
+ l = np.load(os.path.join(data_dir, '%s_label.npy' %idx))
+ labels.append(l)
+
+ self.sample_bboxes = labels
+ if self.phase!='test':
+ self.bboxes = []
+ for i, l in enumerate(labels):
+ if len(l) > 0 :
+ for t in l:
+ if t[3]>sizelim:
+ self.bboxes.append([np.concatenate([[i],t])])
+ if t[3]>sizelim2:
+ self.bboxes+=[[np.concatenate([[i],t])]]*2
+ if t[3]>sizelim3:
+ self.bboxes+=[[np.concatenate([[i],t])]]*4
+ self.bboxes = np.concatenate(self.bboxes,axis = 0)
+
+ self.crop = Crop(config)
+ self.label_mapping = LabelMapping(config, self.phase)
+
+ def __getitem__(self, idx,split=None):
+ t = time.time()
+ np.random.seed(int(str(t%1)[2:7]))#seed according to time
+
+ isRandomImg = False
+ if self.phase !='test':
+ if idx>=len(self.bboxes):
+ isRandom = True
+ idx = idx%len(self.bboxes)
+ isRandomImg = np.random.randint(2)
+ else:
+ isRandom = False
+ else:
+ isRandom = False
+
+ if self.phase != 'test':
+ if not isRandomImg:
+ bbox = self.bboxes[idx]
+ filename = self.filenames[int(bbox[0])]
+ imgs = np.load(filename)[0:self.channel]
+ bboxes = self.sample_bboxes[int(bbox[0])]
+ isScale = self.augtype['scale'] and (self.phase=='train')
+ sample, target, bboxes, coord = self.crop(imgs, bbox[1:], bboxes,isScale,isRandom)
+ if self.phase=='train' and not isRandom:
+ sample, target, bboxes, coord = augment(sample, target, bboxes, coord,
+ ifflip = self.augtype['flip'], ifrotate=self.augtype['rotate'], ifswap = self.augtype['swap'])
+ else:
+ randimid = np.random.randint(len(self.kagglenames))
+ filename = self.kagglenames[randimid]
+ imgs = np.load(filename)[0:self.channel]
+ bboxes = self.sample_bboxes[randimid]
+ isScale = self.augtype['scale'] and (self.phase=='train')
+ sample, target, bboxes, coord = self.crop(imgs, [], bboxes,isScale=False,isRand=True)
+ label = self.label_mapping(sample.shape[1:], target, bboxes)
+ sample = sample.astype(np.float32)
+ #if filename in self.kagglenames:
+ # label[label==-1]=0
+ sample = (sample.astype(np.float32)-128)/128
+ return torch.from_numpy(sample), torch.from_numpy(label), coord
+ else:
+ imgs = np.load(self.filenames[idx])
+ bboxes = self.sample_bboxes[idx]
+ nz, nh, nw = imgs.shape[1:]
+ pz = int(np.ceil(float(nz) / self.stride)) * self.stride
+ ph = int(np.ceil(float(nh) / self.stride)) * self.stride
+ pw = int(np.ceil(float(nw) / self.stride)) * self.stride
+ imgs = np.pad(imgs, [[0,0],[0, pz - nz], [0, ph - nh], [0, pw - nw]], 'constant',constant_values = self.pad_value)
+ xx,yy,zz = np.meshgrid(np.linspace(-0.5,0.5,imgs.shape[1]/self.stride),
+ np.linspace(-0.5,0.5,imgs.shape[2]/self.stride),
+ np.linspace(-0.5,0.5,imgs.shape[3]/self.stride),indexing ='ij')
+ coord = np.concatenate([xx[np.newaxis,...], yy[np.newaxis,...],zz[np.newaxis,:]],0).astype('float32')
+ imgs, nzhw = self.split_comber.split(imgs)
+ coord2, nzhw2 = self.split_comber.split(coord,
+ side_len = self.split_comber.side_len/self.stride,
+ max_stride = self.split_comber.max_stride/self.stride,
+ margin = self.split_comber.margin/self.stride)
+ assert np.all(nzhw==nzhw2)
+ imgs = (imgs.astype(np.float32)-128)/128
+ return torch.from_numpy(imgs.astype(np.float32)), bboxes, torch.from_numpy(coord2.astype(np.float32)), np.array(nzhw)
+
+ def __len__(self):
+ if self.phase == 'train':
+ return len(self.bboxes)/(1-self.r_rand)
+ elif self.phase =='val':
+ return len(self.bboxes)
+ else:
+ return len(self.filenames)
+
+
+def augment(sample, target, bboxes, coord, ifflip = True, ifrotate=True, ifswap = True):
+ # angle1 = np.random.rand()*180
+ if ifrotate:
+ validrot = False
+ counter = 0
+ while not validrot:
+ newtarget = np.copy(target)
+ angle1 = (np.random.rand()-0.5)*20
+ size = np.array(sample.shape[2:4]).astype('float')
+ rotmat = np.array([[np.cos(angle1/180*np.pi),-np.sin(angle1/180*np.pi)],[np.sin(angle1/180*np.pi),np.cos(angle1/180*np.pi)]])
+ newtarget[1:3] = np.dot(rotmat,target[1:3]-size/2)+size/2
+ if np.all(newtarget[:3]>target[3]) and np.all(newtarget[:3]< np.array(sample.shape[1:4])-newtarget[3]):
+ validrot = True
+ target = newtarget
+ sample = rotate(sample,angle1,axes=(2,3),reshape=False)
+ coord = rotate(coord,angle1,axes=(2,3),reshape=False)
+ for box in bboxes:
+ box[1:3] = np.dot(rotmat,box[1:3]-size/2)+size/2
+ else:
+ counter += 1
+ if counter ==3:
+ break
+ if ifswap:
+ if sample.shape[1]==sample.shape[2] and sample.shape[1]==sample.shape[3]:
+ axisorder = np.random.permutation(3)
+ sample = np.transpose(sample,np.concatenate([[0],axisorder+1]))
+ coord = np.transpose(coord,np.concatenate([[0],axisorder+1]))
+ target[:3] = target[:3][axisorder]
+ bboxes[:,:3] = bboxes[:,:3][:,axisorder]
+
+ if ifflip:
+# flipid = np.array([np.random.randint(2),np.random.randint(2),np.random.randint(2)])*2-1
+ flipid = np.array([1,np.random.randint(2),np.random.randint(2)])*2-1
+ sample = np.ascontiguousarray(sample[:,::flipid[0],::flipid[1],::flipid[2]])
+ coord = np.ascontiguousarray(coord[:,::flipid[0],::flipid[1],::flipid[2]])
+ for ax in range(3):
+ if flipid[ax]==-1:
+ target[ax] = np.array(sample.shape[ax+1])-target[ax]
+ bboxes[:,ax]= np.array(sample.shape[ax+1])-bboxes[:,ax]
+ return sample, target, bboxes, coord
+
+class Crop(object):
+ def __init__(self, config):
+ self.crop_size = config['crop_size']
+ self.bound_size = config['bound_size']
+ self.stride = config['stride']
+ self.pad_value = config['pad_value']
+
+ def __call__(self, imgs, target, bboxes,isScale=False,isRand=False):
+ if isScale:
+ radiusLim = [8.,100.]
+ scaleLim = [0.75,1.25]
+ scaleRange = [np.min([np.max([(radiusLim[0]/target[3]),scaleLim[0]]),1])
+ ,np.max([np.min([(radiusLim[1]/target[3]),scaleLim[1]]),1])]
+ scale = np.random.rand()*(scaleRange[1]-scaleRange[0])+scaleRange[0]
+ crop_size = (np.array(self.crop_size).astype('float')/scale).astype('int')
+ else:
+ crop_size=self.crop_size
+ bound_size = self.bound_size
+ target = np.copy(target)
+ bboxes = np.copy(bboxes)
+
+ start = []
+ for i in range(3):
+ if not isRand:
+ r = target[3] / 2
+ s = np.floor(target[i] - r)+ 1 - bound_size
+ e = np.ceil (target[i] + r)+ 1 + bound_size - crop_size[i]
+ else:
+ s = np.max([imgs.shape[i+1]-crop_size[i]/2,imgs.shape[i+1]/2+bound_size])
+ e = np.min([crop_size[i]/2, imgs.shape[i+1]/2-bound_size])
+ target = np.array([np.nan,np.nan,np.nan,np.nan])
+ if s>e:
+ start.append(np.random.randint(e,s))#!
+ else:
+ start.append(int(target[i])-crop_size[i]/2+np.random.randint(-bound_size/2,bound_size/2))
+
+
+ normstart = np.array(start).astype('float32')/np.array(imgs.shape[1:])-0.5
+ normsize = np.array(crop_size).astype('float32')/np.array(imgs.shape[1:])
+ xx,yy,zz = np.meshgrid(np.linspace(normstart[0],normstart[0]+normsize[0],self.crop_size[0]/self.stride),
+ np.linspace(normstart[1],normstart[1]+normsize[1],self.crop_size[1]/self.stride),
+ np.linspace(normstart[2],normstart[2]+normsize[2],self.crop_size[2]/self.stride),indexing ='ij')
+ coord = np.concatenate([xx[np.newaxis,...], yy[np.newaxis,...],zz[np.newaxis,:]],0).astype('float32')
+
+ pad = []
+ pad.append([0,0])
+ for i in range(3):
+ leftpad = max(0,-start[i])
+ rightpad = max(0,start[i]+crop_size[i]-imgs.shape[i+1])
+ pad.append([leftpad,rightpad])
+ crop = imgs[:,
+ max(start[0],0):min(start[0] + crop_size[0],imgs.shape[1]),
+ max(start[1],0):min(start[1] + crop_size[1],imgs.shape[2]),
+ max(start[2],0):min(start[2] + crop_size[2],imgs.shape[3])]
+ crop = np.pad(crop,pad,'constant',constant_values =self.pad_value)
+ for i in range(3):
+ target[i] = target[i] - start[i]
+ for i in range(len(bboxes)):
+ for j in range(3):
+ bboxes[i][j] = bboxes[i][j] - start[j]
+
+ if isScale:
+ with warnings.catch_warnings():
+ warnings.simplefilter("ignore")
+ crop = zoom(crop,[1,scale,scale,scale],order=1)
+ newpad = self.crop_size[0]-crop.shape[1:][0]
+ if newpad<0:
+ crop = crop[:,:-newpad,:-newpad,:-newpad]
+ elif newpad>0:
+ pad2 = [[0,0],[0,newpad],[0,newpad],[0,newpad]]
+ crop = np.pad(crop,pad2,'constant',constant_values =self.pad_value)
+ for i in range(4):
+ target[i] = target[i]*scale
+ for i in range(len(bboxes)):
+ for j in range(4):
+ bboxes[i][j] = bboxes[i][j]*scale
+ return crop, target, bboxes, coord
+
+class LabelMapping(object):
+ def __init__(self, config, phase):
+ self.stride = np.array(config['stride'])
+ self.num_neg = int(config['num_neg'])
+ self.th_neg = config['th_neg']
+ self.anchors = np.asarray(config['anchors'])
+ self.phase = phase
+ if phase == 'train':
+ self.th_pos = config['th_pos_train']
+ elif phase == 'val':
+ self.th_pos = config['th_pos_val']
+
+
+ def __call__(self, input_size, target, bboxes):
+ stride = self.stride
+ num_neg = self.num_neg
+ th_neg = self.th_neg
+ anchors = self.anchors
+ th_pos = self.th_pos
+ struct = generate_binary_structure(3,1)
+
+ output_size = []
+ for i in range(3):
+ assert(input_size[i] % stride == 0)
+ output_size.append(input_size[i] / stride)
+
+ label = np.zeros(output_size + [len(anchors), 5], np.float32)
+ offset = ((stride.astype('float')) - 1) / 2
+ oz = np.arange(offset, offset + stride * (output_size[0] - 1) + 1, stride)
+ oh = np.arange(offset, offset + stride * (output_size[1] - 1) + 1, stride)
+ ow = np.arange(offset, offset + stride * (output_size[2] - 1) + 1, stride)
+
+ for bbox in bboxes:
+ for i, anchor in enumerate(anchors):
+ iz, ih, iw = select_samples(bbox, anchor, th_neg, oz, oh, ow)
+ label[iz, ih, iw, i, 0] = 1
+ label[:,:,:, i, 0] = binary_dilation(label[:,:,:, i, 0].astype('bool'),structure=struct,iterations=1).astype('float32')
+
+
+ label = label-1
+
+ if self.phase == 'train' and self.num_neg > 0:
+ neg_z, neg_h, neg_w, neg_a = np.where(label[:, :, :, :, 0] == -1)
+ neg_idcs = random.sample(range(len(neg_z)), min(num_neg, len(neg_z)))
+ neg_z, neg_h, neg_w, neg_a = neg_z[neg_idcs], neg_h[neg_idcs], neg_w[neg_idcs], neg_a[neg_idcs]
+ label[:, :, :, :, 0] = 0
+ label[neg_z, neg_h, neg_w, neg_a, 0] = -1
+
+ if np.isnan(target[0]):
+ return label
+ iz, ih, iw, ia = [], [], [], []
+ for i, anchor in enumerate(anchors):
+ iiz, iih, iiw = select_samples(target, anchor, th_pos, oz, oh, ow)
+ iz.append(iiz)
+ ih.append(iih)
+ iw.append(iiw)
+ ia.append(i * np.ones((len(iiz),), np.int64))
+ iz = np.concatenate(iz, 0)
+ ih = np.concatenate(ih, 0)
+ iw = np.concatenate(iw, 0)
+ ia = np.concatenate(ia, 0)
+ flag = True
+ if len(iz) == 0:
+ pos = []
+ for i in range(3):
+ pos.append(max(0, int(np.round((target[i] - offset) / stride))))
+ idx = np.argmin(np.abs(np.log(target[3] / anchors)))
+ pos.append(idx)
+ flag = False
+ else:
+ idx = random.sample(range(len(iz)), 1)[0]
+ pos = [iz[idx], ih[idx], iw[idx], ia[idx]]
+ dz = (target[0] - oz[pos[0]]) / anchors[pos[3]]
+ dh = (target[1] - oh[pos[1]]) / anchors[pos[3]]
+ dw = (target[2] - ow[pos[2]]) / anchors[pos[3]]
+ dd = np.log(target[3] / anchors[pos[3]])
+ label[pos[0], pos[1], pos[2], pos[3], :] = [1, dz, dh, dw, dd]
+ return label
+
+def select_samples(bbox, anchor, th, oz, oh, ow):
+ z, h, w, d = bbox
+ max_overlap = min(d, anchor)
+ min_overlap = np.power(max(d, anchor), 3) * th / max_overlap / max_overlap
+ if min_overlap > max_overlap:
+ return np.zeros((0,), np.int64), np.zeros((0,), np.int64), np.zeros((0,), np.int64)
+ else:
+ s = z - 0.5 * np.abs(d - anchor) - (max_overlap - min_overlap)
+ e = z + 0.5 * np.abs(d - anchor) + (max_overlap - min_overlap)
+ mz = np.logical_and(oz >= s, oz <= e)
+ iz = np.where(mz)[0]
+
+ s = h - 0.5 * np.abs(d - anchor) - (max_overlap - min_overlap)
+ e = h + 0.5 * np.abs(d - anchor) + (max_overlap - min_overlap)
+ mh = np.logical_and(oh >= s, oh <= e)
+ ih = np.where(mh)[0]
+
+ s = w - 0.5 * np.abs(d - anchor) - (max_overlap - min_overlap)
+ e = w + 0.5 * np.abs(d - anchor) + (max_overlap - min_overlap)
+ mw = np.logical_and(ow >= s, ow <= e)
+ iw = np.where(mw)[0]
+
+ if len(iz) == 0 or len(ih) == 0 or len(iw) == 0:
+ return np.zeros((0,), np.int64), np.zeros((0,), np.int64), np.zeros((0,), np.int64)
+
+ lz, lh, lw = len(iz), len(ih), len(iw)
+ iz = iz.reshape((-1, 1, 1))
+ ih = ih.reshape((1, -1, 1))
+ iw = iw.reshape((1, 1, -1))
+ iz = np.tile(iz, (1, lh, lw)).reshape((-1))
+ ih = np.tile(ih, (lz, 1, lw)).reshape((-1))
+ iw = np.tile(iw, (lz, lh, 1)).reshape((-1))
+ centers = np.concatenate([
+ oz[iz].reshape((-1, 1)),
+ oh[ih].reshape((-1, 1)),
+ ow[iw].reshape((-1, 1))], axis = 1)
+
+ r0 = anchor / 2
+ s0 = centers - r0
+ e0 = centers + r0
+
+ r1 = d / 2
+ s1 = bbox[:3] - r1
+ s1 = s1.reshape((1, -1))
+ e1 = bbox[:3] + r1
+ e1 = e1.reshape((1, -1))
+
+ overlap = np.maximum(0, np.minimum(e0, e1) - np.maximum(s0, s1))
+
+ intersection = overlap[:, 0] * overlap[:, 1] * overlap[:, 2]
+ union = anchor * anchor * anchor + d * d * d - intersection
+
+ iou = intersection / union
+
+ mask = iou >= th
+ #if th > 0.4:
+ # if np.sum(mask) == 0:
+ # print(['iou not large', iou.max()])
+ # else:
+ # print(['iou large', iou[mask]])
+ iz = iz[mask]
+ ih = ih[mask]
+ iw = iw[mask]
+ return iz, ih, iw
+
+def collate(batch):
+ if torch.is_tensor(batch[0]):
+ return [b.unsqueeze(0) for b in batch]
+ elif isinstance(batch[0], np.ndarray):
+ return batch
+ elif isinstance(batch[0], int):
+ return torch.LongTensor(batch)
+ elif isinstance(batch[0], collections.Iterable):
+ transposed = zip(*batch)
+ return [collate(samples) for samples in transposed]
+
diff --git a/images/casenet.png b/images/casenet.png
new file mode 100644
index 0000000..23518cf
Binary files /dev/null and b/images/casenet.png differ
diff --git a/images/nodulenet.png b/images/nodulenet.png
new file mode 100644
index 0000000..00e4b99
Binary files /dev/null and b/images/nodulenet.png differ
diff --git a/layers.py b/layers.py
new file mode 100644
index 0000000..939b7be
--- /dev/null
+++ b/layers.py
@@ -0,0 +1,359 @@
+import numpy as np
+
+import torch
+from torch import nn
+import math
+
+class PostRes2d(nn.Module):
+ def __init__(self, n_in, n_out, stride = 1):
+ super(PostRes2d, self).__init__()
+ self.conv1 = nn.Conv2d(n_in, n_out, kernel_size = 3, stride = stride, padding = 1)
+ self.bn1 = nn.BatchNorm2d(n_out)
+ self.relu = nn.ReLU(inplace = True)
+ self.conv2 = nn.Conv2d(n_out, n_out, kernel_size = 3, padding = 1)
+ self.bn2 = nn.BatchNorm2d(n_out)
+
+ if stride != 1 or n_out != n_in:
+ self.shortcut = nn.Sequential(
+ nn.Conv2d(n_in, n_out, kernel_size = 1, stride = stride),
+ nn.BatchNorm2d(n_out))
+ else:
+ self.shortcut = None
+
+ def forward(self, x):
+ residual = x
+ if self.shortcut is not None:
+ residual = self.shortcut(x)
+ out = self.conv1(x)
+ out = self.bn1(out)
+ out = self.relu(out)
+ out = self.conv2(out)
+ out = self.bn2(out)
+
+ out += residual
+ out = self.relu(out)
+ return out
+
+class PostRes(nn.Module):
+ def __init__(self, n_in, n_out, stride = 1):
+ super(PostRes, self).__init__()
+ self.conv1 = nn.Conv3d(n_in, n_out, kernel_size = 3, stride = stride, padding = 1)
+ self.bn1 = nn.BatchNorm3d(n_out)
+ self.relu = nn.ReLU(inplace = True)
+ self.conv2 = nn.Conv3d(n_out, n_out, kernel_size = 3, padding = 1)
+ self.bn2 = nn.BatchNorm3d(n_out)
+
+ if stride != 1 or n_out != n_in:
+ self.shortcut = nn.Sequential(
+ nn.Conv3d(n_in, n_out, kernel_size = 1, stride = stride),
+ nn.BatchNorm3d(n_out))
+ else:
+ self.shortcut = None
+
+ def forward(self, x):
+ residual = x
+ if self.shortcut is not None:
+ residual = self.shortcut(x)
+ out = self.conv1(x)
+ out = self.bn1(out)
+ out = self.relu(out)
+ out = self.conv2(out)
+ out = self.bn2(out)
+
+ out += residual
+ out = self.relu(out)
+ return out
+
+class Rec3(nn.Module):
+ def __init__(self, n0, n1, n2, n3, p = 0.0, integrate = True):
+ super(Rec3, self).__init__()
+
+ self.block01 = nn.Sequential(
+ nn.Conv3d(n0, n1, kernel_size = 3, stride = 2, padding = 1),
+ nn.BatchNorm3d(n1),
+ nn.ReLU(inplace = True),
+ nn.Conv3d(n1, n1, kernel_size = 3, padding = 1),
+ nn.BatchNorm3d(n1))
+
+ self.block11 = nn.Sequential(
+ nn.Conv3d(n1, n1, kernel_size = 3, padding = 1),
+ nn.BatchNorm3d(n1),
+ nn.ReLU(inplace = True),
+ nn.Conv3d(n1, n1, kernel_size = 3, padding = 1),
+ nn.BatchNorm3d(n1))
+
+ self.block21 = nn.Sequential(
+ nn.ConvTranspose3d(n2, n1, kernel_size = 2, stride = 2),
+ nn.BatchNorm3d(n1),
+ nn.ReLU(inplace = True),
+ nn.Conv3d(n1, n1, kernel_size = 3, padding = 1),
+ nn.BatchNorm3d(n1))
+
+ self.block12 = nn.Sequential(
+ nn.Conv3d(n1, n2, kernel_size = 3, stride = 2, padding = 1),
+ nn.BatchNorm3d(n2),
+ nn.ReLU(inplace = True),
+ nn.Conv3d(n2, n2, kernel_size = 3, padding = 1),
+ nn.BatchNorm3d(n2))
+
+ self.block22 = nn.Sequential(
+ nn.Conv3d(n2, n2, kernel_size = 3, padding = 1),
+ nn.BatchNorm3d(n2),
+ nn.ReLU(inplace = True),
+ nn.Conv3d(n2, n2, kernel_size = 3, padding = 1),
+ nn.BatchNorm3d(n2))
+
+ self.block32 = nn.Sequential(
+ nn.ConvTranspose3d(n3, n2, kernel_size = 2, stride = 2),
+ nn.BatchNorm3d(n2),
+ nn.ReLU(inplace = True),
+ nn.Conv3d(n2, n2, kernel_size = 3, padding = 1),
+ nn.BatchNorm3d(n2))
+
+ self.block23 = nn.Sequential(
+ nn.Conv3d(n2, n3, kernel_size = 3, stride = 2, padding = 1),
+ nn.BatchNorm3d(n3),
+ nn.ReLU(inplace = True),
+ nn.Conv3d(n3, n3, kernel_size = 3, padding = 1),
+ nn.BatchNorm3d(n3))
+
+ self.block33 = nn.Sequential(
+ nn.Conv3d(n3, n3, kernel_size = 3, padding = 1),
+ nn.BatchNorm3d(n3),
+ nn.ReLU(inplace = True),
+ nn.Conv3d(n3, n3, kernel_size = 3, padding = 1),
+ nn.BatchNorm3d(n3))
+
+ self.relu = nn.ReLU(inplace = True)
+ self.p = p
+ self.integrate = integrate
+
+ def forward(self, x0, x1, x2, x3):
+ if self.p > 0 and self.training:
+ coef = torch.bernoulli((1.0 - self.p) * torch.ones(8))
+ out1 = coef[0] * self.block01(x0) + coef[1] * self.block11(x1) + coef[2] * self.block21(x2)
+ out2 = coef[3] * self.block12(x1) + coef[4] * self.block22(x2) + coef[5] * self.block32(x3)
+ out3 = coef[6] * self.block23(x2) + coef[7] * self.block33(x3)
+ else:
+ out1 = (1 - self.p) * (self.block01(x0) + self.block11(x1) + self.block21(x2))
+ out2 = (1 - self.p) * (self.block12(x1) + self.block22(x2) + self.block32(x3))
+ out3 = (1 - self.p) * (self.block23(x2) + self.block33(x3))
+
+ if self.integrate:
+ out1 += x1
+ out2 += x2
+ out3 += x3
+
+ return x0, self.relu(out1), self.relu(out2), self.relu(out3)
+
+def hard_mining(neg_output, neg_labels, num_hard):
+ _, idcs = torch.topk(neg_output, min(num_hard, len(neg_output)))
+ neg_output = torch.index_select(neg_output, 0, idcs)
+ neg_labels = torch.index_select(neg_labels, 0, idcs)
+ return neg_output, neg_labels
+
+class Loss(nn.Module):
+ def __init__(self, num_hard = 0):
+ super(Loss, self).__init__()
+ self.sigmoid = nn.Sigmoid()
+ self.classify_loss = nn.BCELoss()
+ self.regress_loss = nn.SmoothL1Loss()
+ self.num_hard = num_hard
+
+ def forward(self, output, labels, train = True):
+ batch_size = labels.size(0)
+ output = output.view(-1, 5)
+ labels = labels.view(-1, 5)
+
+ pos_idcs = labels[:, 0] > 0.5
+ pos_idcs = pos_idcs.unsqueeze(1).expand(pos_idcs.size(0), 5)
+ pos_output = output[pos_idcs].view(-1, 5)
+ pos_labels = labels[pos_idcs].view(-1, 5)
+
+ neg_idcs = labels[:, 0] < -0.5
+ neg_output = output[:, 0][neg_idcs]
+ neg_labels = labels[:, 0][neg_idcs]
+
+ if self.num_hard > 0 and train:
+ neg_output, neg_labels = hard_mining(neg_output, neg_labels, self.num_hard * batch_size)
+ neg_prob = self.sigmoid(neg_output)
+
+ #classify_loss = self.classify_loss(
+ # torch.cat((pos_prob, neg_prob), 0),
+ # torch.cat((pos_labels[:, 0], neg_labels + 1), 0))
+ if len(pos_output)>0:
+ pos_prob = self.sigmoid(pos_output[:, 0])
+ pz, ph, pw, pd = pos_output[:, 1], pos_output[:, 2], pos_output[:, 3], pos_output[:, 4]
+ lz, lh, lw, ld = pos_labels[:, 1], pos_labels[:, 2], pos_labels[:, 3], pos_labels[:, 4]
+
+ regress_losses = [
+ self.regress_loss(pz, lz),
+ self.regress_loss(ph, lh),
+ self.regress_loss(pw, lw),
+ self.regress_loss(pd, ld)]
+ regress_losses_data = [l.data[0] for l in regress_losses]
+ classify_loss = 0.5 * self.classify_loss(
+ pos_prob, pos_labels[:, 0]) + 0.5 * self.classify_loss(
+ neg_prob, neg_labels + 1)
+ pos_correct = (pos_prob.data >= 0.5).sum()
+ pos_total = len(pos_prob)
+
+ else:
+ regress_losses = [0,0,0,0]
+ classify_loss = 0.5 * self.classify_loss(
+ neg_prob, neg_labels + 1)
+ pos_correct = 0
+ pos_total = 0
+ regress_losses_data = [0,0,0,0]
+ classify_loss_data = classify_loss.data[0]
+
+ loss = classify_loss
+ for regress_loss in regress_losses:
+ loss += regress_loss
+
+ neg_correct = (neg_prob.data < 0.5).sum()
+ neg_total = len(neg_prob)
+
+ return [loss, classify_loss_data] + regress_losses_data + [pos_correct, pos_total, neg_correct, neg_total]
+
+class GetPBB(object):
+ def __init__(self, config):
+ self.stride = config['stride']
+ self.anchors = np.asarray(config['anchors'])
+
+ def __call__(self, output,thresh = -3, ismask=False):
+ stride = self.stride
+ anchors = self.anchors
+ output = np.copy(output)
+ offset = (float(stride) - 1) / 2
+ output_size = output.shape
+ oz = np.arange(offset, offset + stride * (output_size[0] - 1) + 1, stride)
+ oh = np.arange(offset, offset + stride * (output_size[1] - 1) + 1, stride)
+ ow = np.arange(offset, offset + stride * (output_size[2] - 1) + 1, stride)
+
+ output[:, :, :, :, 1] = oz.reshape((-1, 1, 1, 1)) + output[:, :, :, :, 1] * anchors.reshape((1, 1, 1, -1))
+ output[:, :, :, :, 2] = oh.reshape((1, -1, 1, 1)) + output[:, :, :, :, 2] * anchors.reshape((1, 1, 1, -1))
+ output[:, :, :, :, 3] = ow.reshape((1, 1, -1, 1)) + output[:, :, :, :, 3] * anchors.reshape((1, 1, 1, -1))
+ output[:, :, :, :, 4] = np.exp(output[:, :, :, :, 4]) * anchors.reshape((1, 1, 1, -1))
+ mask = output[..., 0] > thresh
+ xx,yy,zz,aa = np.where(mask)
+
+ output = output[xx,yy,zz,aa]
+ if ismask:
+ return output,[xx,yy,zz,aa]
+ else:
+ return output
+
+ #output = output[output[:, 0] >= self.conf_th]
+ #bboxes = nms(output, self.nms_th)
+def nms(output, nms_th):
+ if len(output) == 0:
+ return output
+
+ output = output[np.argsort(-output[:, 0])]
+ bboxes = [output[0]]
+
+ for i in np.arange(1, len(output)):
+ bbox = output[i]
+ flag = 1
+ for j in range(len(bboxes)):
+ if iou(bbox[1:5], bboxes[j][1:5]) >= nms_th:
+ flag = -1
+ break
+ if flag == 1:
+ bboxes.append(bbox)
+
+ bboxes = np.asarray(bboxes, np.float32)
+ return bboxes
+
+def iou(box0, box1):
+
+ r0 = box0[3] / 2
+ s0 = box0[:3] - r0
+ e0 = box0[:3] + r0
+
+ r1 = box1[3] / 2
+ s1 = box1[:3] - r1
+ e1 = box1[:3] + r1
+
+ overlap = []
+ for i in range(len(s0)):
+ overlap.append(max(0, min(e0[i], e1[i]) - max(s0[i], s1[i])))
+
+ intersection = overlap[0] * overlap[1] * overlap[2]
+ union = box0[3] * box0[3] * box0[3] + box1[3] * box1[3] * box1[3] - intersection
+ return intersection / union
+
+def acc(pbb, lbb, conf_th, nms_th, detect_th):
+ pbb = pbb[pbb[:, 0] >= conf_th]
+ pbb = nms(pbb, nms_th)
+
+ tp = []
+ fp = []
+ fn = []
+ l_flag = np.zeros((len(lbb),), np.int32)
+ for p in pbb:
+ flag = 0
+ bestscore = 0
+ for i, l in enumerate(lbb):
+ score = iou(p[1:5], l)
+ if score>bestscore:
+ bestscore = score
+ besti = i
+ if bestscore > detect_th:
+ flag = 1
+ if l_flag[besti] == 0:
+ l_flag[besti] = 1
+ tp.append(np.concatenate([p,[bestscore]],0))
+ else:
+ fp.append(np.concatenate([p,[bestscore]],0))
+ if flag == 0:
+ fp.append(np.concatenate([p,[bestscore]],0))
+ for i,l in enumerate(lbb):
+ if l_flag[i]==0:
+ score = []
+ for p in pbb:
+ score.append(iou(p[1:5],l))
+ if len(score)!=0:
+ bestscore = np.max(score)
+ else:
+ bestscore = 0
+ if bestscore0:
+ fn = np.concatenate([fn,tp[fn_i,:5]])
+ else:
+ fn = fn
+ if len(tp_in_topk)>0:
+ tp = tp[tp_in_topk]
+ else:
+ tp = []
+ if len(fp_in_topk)>0:
+ fp = newallp[fp_in_topk]
+ else:
+ fp = []
+ return tp, fp , fn
diff --git a/main.py b/main.py
new file mode 100644
index 0000000..da479e6
--- /dev/null
+++ b/main.py
@@ -0,0 +1,109 @@
+from preprocessing import full_prep
+from config_submit import config as config_submit
+
+import torch
+from torch.nn import DataParallel
+from torch.backends import cudnn
+from torch.utils.data import DataLoader
+from torch import optim
+from torch.autograd import Variable
+
+from layers import acc
+from data_detector import DataBowl3Detector,collate
+from data_classifier import DataBowl3Classifier
+
+from utils import *
+from split_combine import SplitComb
+from test_detect import test_detect
+from importlib import import_module
+import pandas
+
+datapath = config_submit['datapath']
+prep_result_path = config_submit['preprocess_result_path']
+skip_prep = config_submit['skip_preprocessing']
+skip_detect = config_submit['skip_detect']
+
+if not skip_prep:
+ testsplit = full_prep(datapath,prep_result_path,
+ n_worker = config_submit['n_worker_preprocessing'],
+ use_existing=config_submit['use_exsiting_preprocessing'])
+else:
+ testsplit = os.listdir(datapath)
+
+nodmodel = import_module(config_submit['detector_model'].split('.py')[0])
+config1, nod_net, loss, get_pbb = nodmodel.get_model()
+checkpoint = torch.load(config_submit['detector_param'])
+nod_net.load_state_dict(checkpoint['state_dict'])
+
+torch.cuda.set_device(0)
+nod_net = nod_net.cuda()
+cudnn.benchmark = True
+nod_net = DataParallel(nod_net)
+
+bbox_result_path = './bbox_result'
+if not os.path.exists(bbox_result_path):
+ os.mkdir(bbox_result_path)
+#testsplit = [f.split('_clean')[0] for f in os.listdir(prep_result_path) if '_clean' in f]
+
+if not skip_detect:
+ margin = 32
+ sidelen = 144
+ config1['datadir'] = prep_result_path
+ split_comber = SplitComb(sidelen,config1['max_stride'],config1['stride'],margin,pad_value= config1['pad_value'])
+
+ dataset = DataBowl3Detector(testsplit,config1,phase='test',split_comber=split_comber)
+ test_loader = DataLoader(dataset,batch_size = 1,
+ shuffle = False,num_workers = 32,pin_memory=False,collate_fn =collate)
+
+ test_detect(test_loader, nod_net, get_pbb, bbox_result_path,config1,n_gpu=config_submit['n_gpu'])
+
+
+
+
+casemodel = import_module(config_submit['classifier_model'].split('.py')[0])
+casenet = casemodel.CaseNet(topk=5)
+config2 = casemodel.config
+checkpoint = torch.load(config_submit['classifier_param'])
+casenet.load_state_dict(checkpoint['state_dict'])
+
+torch.cuda.set_device(0)
+casenet = casenet.cuda()
+cudnn.benchmark = True
+casenet = DataParallel(casenet)
+
+filename = config_submit['outputfile']
+
+
+
+def test_casenet(model,testset):
+ data_loader = DataLoader(
+ testset,
+ batch_size = 1,
+ shuffle = False,
+ num_workers = 32,
+ pin_memory=True)
+ #model = model.cuda()
+ model.eval()
+ predlist = []
+
+ # weight = torch.from_numpy(np.ones_like(y).float().cuda()
+ for i,(x,coord) in enumerate(data_loader):
+
+ coord = Variable(coord).cuda()
+ x = Variable(x).cuda()
+ nodulePred,casePred,_ = model(x,coord)
+ predlist.append(casePred.data.cpu().numpy())
+ #print([i,data_loader.dataset.split[i,1],casePred.data.cpu().numpy()])
+ predlist = np.concatenate(predlist)
+ return predlist
+config2['bboxpath'] = bbox_result_path
+config2['datadir'] = prep_result_path
+
+
+
+dataset = DataBowl3Classifier(testsplit, config2, phase = 'test')
+predlist = test_casenet(casenet,dataset).T
+anstable = np.concatenate([[testsplit],predlist],0).T
+df = pandas.DataFrame(anstable)
+df.columns={'id','cancer'}
+df.to_csv(filename,index=False)
diff --git a/model/classifier.ckpt b/model/classifier.ckpt
new file mode 100644
index 0000000..b9e9523
Binary files /dev/null and b/model/classifier.ckpt differ
diff --git a/model/detector.ckpt b/model/detector.ckpt
new file mode 100644
index 0000000..04215a7
Binary files /dev/null and b/model/detector.ckpt differ
diff --git a/net_classifier.py b/net_classifier.py
new file mode 100644
index 0000000..d467404
--- /dev/null
+++ b/net_classifier.py
@@ -0,0 +1,173 @@
+import torch
+from torch import nn
+from layers import *
+from torch.nn import DataParallel
+from torch.backends import cudnn
+from torch.utils.data import DataLoader
+from torch import optim
+from torch.autograd import Variable
+from torch.utils.data import Dataset
+from scipy.ndimage.interpolation import rotate
+import numpy as np
+import os
+
+config = {}
+config['topk'] = 5
+config['resample'] = None
+config['datadir'] = '/run/shm/preprocess_1_3/'
+config['preload_train'] = True
+config['bboxpath'] = '../cpliangming/results/res18_prep3/bbox/'
+config['labelfile'] = '../stage1_labels.csv'
+config['preload_val'] = True
+
+config['padmask'] = False
+
+config['crop_size'] = [96,96,96]
+config['scaleLim'] = [0.85,1.15]
+config['radiusLim'] = [6,100]
+config['jitter_range'] = 0.15
+config['isScale'] = True
+
+config['random_sample'] = True
+config['T'] = 1
+config['topk'] = 5
+config['stride'] = 4
+config['augtype'] = {'flip':True,'swap':False,'rotate':False,'scale':False}
+
+config['detect_th'] = 0.05
+config['conf_th'] = -1
+config['nms_th'] = 0.05
+config['filling_value'] = 160
+
+config['startepoch'] = 20
+config['lr_stage'] = np.array([50,100,140,160])
+config['lr'] = [0.01,0.001,0.0001,0.00001]
+config['miss_ratio'] = 1
+config['miss_thresh'] = 0.03
+config['anchors'] = [10,30,60]
+
+class Net(nn.Module):
+ def __init__(self):
+ super(Net, self).__init__()
+ # The first few layers consumes the most memory, so use simple convolution to save memory.
+ # Call these layers preBlock, i.e., before the residual blocks of later layers.
+ self.preBlock = nn.Sequential(
+ nn.Conv3d(1, 24, kernel_size = 3, padding = 1),
+ nn.BatchNorm3d(24),
+ nn.ReLU(inplace = True),
+ nn.Conv3d(24, 24, kernel_size = 3, padding = 1),
+ nn.BatchNorm3d(24),
+ nn.ReLU(inplace = True))
+
+ # 3 poolings, each pooling downsamples the feature map by a factor 2.
+ # 3 groups of blocks. The first block of each group has one pooling.
+ num_blocks_forw = [2,2,3,3]
+ num_blocks_back = [3,3]
+ self.featureNum_forw = [24,32,64,64,64]
+ self.featureNum_back = [128,64,64]
+ for i in range(len(num_blocks_forw)):
+ blocks = []
+ for j in range(num_blocks_forw[i]):
+ if j == 0:
+ blocks.append(PostRes(self.featureNum_forw[i], self.featureNum_forw[i+1]))
+ else:
+ blocks.append(PostRes(self.featureNum_forw[i+1], self.featureNum_forw[i+1]))
+ setattr(self, 'forw' + str(i + 1), nn.Sequential(*blocks))
+
+
+ for i in range(len(num_blocks_back)):
+ blocks = []
+ for j in range(num_blocks_back[i]):
+ if j == 0:
+ if i==0:
+ addition = 3
+ else:
+ addition = 0
+ blocks.append(PostRes(self.featureNum_back[i+1]+self.featureNum_forw[i+2]+addition, self.featureNum_back[i]))
+ else:
+ blocks.append(PostRes(self.featureNum_back[i], self.featureNum_back[i]))
+ setattr(self, 'back' + str(i + 2), nn.Sequential(*blocks))
+
+ self.maxpool1 = nn.MaxPool3d(kernel_size=2,stride=2,return_indices =True)
+ self.maxpool2 = nn.MaxPool3d(kernel_size=2,stride=2,return_indices =True)
+ self.maxpool3 = nn.MaxPool3d(kernel_size=2,stride=2,return_indices =True)
+ self.maxpool4 = nn.MaxPool3d(kernel_size=2,stride=2,return_indices =True)
+ self.unmaxpool1 = nn.MaxUnpool3d(kernel_size=2,stride=2)
+ self.unmaxpool2 = nn.MaxUnpool3d(kernel_size=2,stride=2)
+
+ self.path1 = nn.Sequential(
+ nn.ConvTranspose3d(64, 64, kernel_size = 2, stride = 2),
+ nn.BatchNorm3d(64),
+ nn.ReLU(inplace = True))
+ self.path2 = nn.Sequential(
+ nn.ConvTranspose3d(64, 64, kernel_size = 2, stride = 2),
+ nn.BatchNorm3d(64),
+ nn.ReLU(inplace = True))
+ self.drop = nn.Dropout3d(p = 0.2, inplace = False)
+ self.output = nn.Sequential(nn.Conv3d(self.featureNum_back[0], 64, kernel_size = 1),
+ nn.ReLU(),
+ #nn.Dropout3d(p = 0.3),
+ nn.Conv3d(64, 5 * len(config['anchors']), kernel_size = 1))
+
+ def forward(self, x, coord):
+ out = self.preBlock(x)#16
+ out_pool,indices0 = self.maxpool1(out)
+ out1 = self.forw1(out_pool)#32
+ out1_pool,indices1 = self.maxpool2(out1)
+ out2 = self.forw2(out1_pool)#64
+ #out2 = self.drop(out2)
+ out2_pool,indices2 = self.maxpool3(out2)
+ out3 = self.forw3(out2_pool)#96
+ out3_pool,indices3 = self.maxpool4(out3)
+ out4 = self.forw4(out3_pool)#96
+ #out4 = self.drop(out4)
+
+ rev3 = self.path1(out4)
+ comb3 = self.back3(torch.cat((rev3, out3), 1))#96+96
+ #comb3 = self.drop(comb3)
+ rev2 = self.path2(comb3)
+
+ feat = self.back2(torch.cat((rev2, out2,coord), 1))#64+64
+ comb2 = self.drop(feat)
+ out = self.output(comb2)
+ size = out.size()
+ out = out.view(out.size(0), out.size(1), -1)
+ #out = out.transpose(1, 4).transpose(1, 2).transpose(2, 3).contiguous()
+ out = out.transpose(1, 2).contiguous().view(size[0], size[2], size[3], size[4], len(config['anchors']), 5)
+ #out = out.view(-1, 5)
+ return feat,out
+
+
+class CaseNet(nn.Module):
+ def __init__(self,topk):
+ super(CaseNet,self).__init__()
+ self.NoduleNet = Net()
+ self.fc1 = nn.Linear(128,64)
+ self.fc2 = nn.Linear(64,1)
+ self.pool = nn.MaxPool3d(kernel_size=2)
+ self.dropout = nn.Dropout(0.5)
+ self.baseline = nn.Parameter(torch.Tensor([-30.0]).float())
+ self.Relu = nn.ReLU()
+ def forward(self,xlist,coordlist):
+# xlist: n x k x 1x 96 x 96 x 96
+# coordlist: n x k x 3 x 24 x 24 x 24
+ xsize = xlist.size()
+ corrdsize = coordlist.size()
+ xlist = xlist.view(-1,xsize[2],xsize[3],xsize[4],xsize[5])
+ coordlist = coordlist.view(-1,corrdsize[2],corrdsize[3],corrdsize[4],corrdsize[5])
+
+ noduleFeat,nodulePred = self.NoduleNet(xlist,coordlist)
+ nodulePred = nodulePred.contiguous().view(corrdsize[0],corrdsize[1],-1)
+
+ featshape = noduleFeat.size()#nk x 128 x 24 x 24 x24
+ centerFeat = self.pool(noduleFeat[:,:,featshape[2]/2-1:featshape[2]/2+1,
+ featshape[3]/2-1:featshape[3]/2+1,
+ featshape[4]/2-1:featshape[4]/2+1])
+ centerFeat = centerFeat[:,:,0,0,0]
+ out = self.dropout(centerFeat)
+ out = self.Relu(self.fc1(out))
+ out = torch.sigmoid(self.fc2(out))
+ out = out.view(xsize[0],xsize[1])
+ base_prob = torch.sigmoid(self.baseline)
+ casePred = 1-torch.prod(1-out,dim=1)*(1-base_prob.expand(out.size()[0]))
+ return nodulePred,casePred,out
diff --git a/net_detector.py b/net_detector.py
new file mode 100644
index 0000000..e993c7c
--- /dev/null
+++ b/net_detector.py
@@ -0,0 +1,133 @@
+import torch
+from torch import nn
+from layers import *
+
+config = {}
+config['anchors'] = [ 10.0, 30.0, 60.]
+config['chanel'] = 1
+config['crop_size'] = [128, 128, 128]
+config['stride'] = 4
+config['datadir'] = '/run/shm/preprocess_1_3/'
+
+config['max_stride'] = 16
+config['num_neg'] = 800
+config['th_neg'] = 0.02
+config['th_pos_train'] = 0.5
+config['th_pos_val'] = 1
+config['num_hard'] = 2
+config['bound_size'] = 12
+config['reso'] = 1
+config['sizelim'] = 6. #mm
+config['sizelim2'] = 30
+config['sizelim3'] = 40
+config['aug_scale'] = True
+config['r_rand_crop'] = 0.3
+config['pad_value'] = 170
+config['luna_raw'] = True
+config['cleanimg'] = True
+config['augtype'] = {'flip':True,'swap':False,'scale':True,'rotate':False}
+config['blacklist'] = ['868b024d9fa388b7ddab12ec1c06af38','990fbe3f0a1b53878669967b9afd1441','adc3bbc63d40f8761c59be10f1e504c3']
+
+
+config['lr_stage'] = np.array([50,100,120])
+config['lr'] = [0.01,0.001,0.0001]
+
+#config['blacklist'] = ['868b024d9fa388b7ddab12ec1c06af38','d92998a73d4654a442e6d6ba15bbb827','990fbe3f0a1b53878669967b9afd1441','820245d8b211808bd18e78ff5be16fdb','adc3bbc63d40f8761c59be10f1e504c3',
+# '417','077','188','876','057','087','130','468']
+
+class Net(nn.Module):
+ def __init__(self):
+ super(Net, self).__init__()
+ # The first few layers consumes the most memory, so use simple convolution to save memory.
+ # Call these layers preBlock, i.e., before the residual blocks of later layers.
+ self.preBlock = nn.Sequential(
+ nn.Conv3d(1, 24, kernel_size = 3, padding = 1),
+ nn.BatchNorm3d(24),
+ nn.ReLU(inplace = True),
+ nn.Conv3d(24, 24, kernel_size = 3, padding = 1),
+ nn.BatchNorm3d(24),
+ nn.ReLU(inplace = True))
+
+ # 3 poolings, each pooling downsamples the feature map by a factor 2.
+ # 3 groups of blocks. The first block of each group has one pooling.
+ num_blocks_forw = [2,2,3,3]
+ num_blocks_back = [3,3]
+ self.featureNum_forw = [24,32,64,64,64]
+ self.featureNum_back = [128,64,64]
+ for i in range(len(num_blocks_forw)):
+ blocks = []
+ for j in range(num_blocks_forw[i]):
+ if j == 0:
+ blocks.append(PostRes(self.featureNum_forw[i], self.featureNum_forw[i+1]))
+ else:
+ blocks.append(PostRes(self.featureNum_forw[i+1], self.featureNum_forw[i+1]))
+ setattr(self, 'forw' + str(i + 1), nn.Sequential(*blocks))
+
+
+ for i in range(len(num_blocks_back)):
+ blocks = []
+ for j in range(num_blocks_back[i]):
+ if j == 0:
+ if i==0:
+ addition = 3
+ else:
+ addition = 0
+ blocks.append(PostRes(self.featureNum_back[i+1]+self.featureNum_forw[i+2]+addition, self.featureNum_back[i]))
+ else:
+ blocks.append(PostRes(self.featureNum_back[i], self.featureNum_back[i]))
+ setattr(self, 'back' + str(i + 2), nn.Sequential(*blocks))
+
+ self.maxpool1 = nn.MaxPool3d(kernel_size=2,stride=2,return_indices =True)
+ self.maxpool2 = nn.MaxPool3d(kernel_size=2,stride=2,return_indices =True)
+ self.maxpool3 = nn.MaxPool3d(kernel_size=2,stride=2,return_indices =True)
+ self.maxpool4 = nn.MaxPool3d(kernel_size=2,stride=2,return_indices =True)
+ self.unmaxpool1 = nn.MaxUnpool3d(kernel_size=2,stride=2)
+ self.unmaxpool2 = nn.MaxUnpool3d(kernel_size=2,stride=2)
+
+ self.path1 = nn.Sequential(
+ nn.ConvTranspose3d(64, 64, kernel_size = 2, stride = 2),
+ nn.BatchNorm3d(64),
+ nn.ReLU(inplace = True))
+ self.path2 = nn.Sequential(
+ nn.ConvTranspose3d(64, 64, kernel_size = 2, stride = 2),
+ nn.BatchNorm3d(64),
+ nn.ReLU(inplace = True))
+ self.drop = nn.Dropout3d(p = 0.2, inplace = False)
+ self.output = nn.Sequential(nn.Conv3d(self.featureNum_back[0], 64, kernel_size = 1),
+ nn.ReLU(),
+ #nn.Dropout3d(p = 0.3),
+ nn.Conv3d(64, 5 * len(config['anchors']), kernel_size = 1))
+
+ def forward(self, x, coord):
+ out = self.preBlock(x)#16
+ out_pool,indices0 = self.maxpool1(out)
+ out1 = self.forw1(out_pool)#32
+ out1_pool,indices1 = self.maxpool2(out1)
+ out2 = self.forw2(out1_pool)#64
+ #out2 = self.drop(out2)
+ out2_pool,indices2 = self.maxpool3(out2)
+ out3 = self.forw3(out2_pool)#96
+ out3_pool,indices3 = self.maxpool4(out3)
+ out4 = self.forw4(out3_pool)#96
+ #out4 = self.drop(out4)
+
+ rev3 = self.path1(out4)
+ comb3 = self.back3(torch.cat((rev3, out3), 1))#96+96
+ #comb3 = self.drop(comb3)
+ rev2 = self.path2(comb3)
+
+ feat = self.back2(torch.cat((rev2, out2,coord), 1))#64+64
+ comb2 = self.drop(feat)
+ out = self.output(comb2)
+ size = out.size()
+ out = out.view(out.size(0), out.size(1), -1)
+ #out = out.transpose(1, 4).transpose(1, 2).transpose(2, 3).contiguous()
+ out = out.transpose(1, 2).contiguous().view(size[0], size[2], size[3], size[4], len(config['anchors']), 5)
+ #out = out.view(-1, 5)
+ return out
+
+def get_model():
+ net = Net()
+ loss = Loss(config['num_hard'])
+ get_pbb = GetPBB(config)
+ return config, net, loss, get_pbb
diff --git a/prep_result/.gitignore b/prep_result/.gitignore
new file mode 100644
index 0000000..76bedae
--- /dev/null
+++ b/prep_result/.gitignore
@@ -0,0 +1,5 @@
+# Ignore everything in this directory
+*
+# Except this file
+!.gitignore
+
diff --git a/preprocessing/AddSegmentation.asv b/preprocessing/AddSegmentation.asv
new file mode 100644
index 0000000..cac82c1
--- /dev/null
+++ b/preprocessing/AddSegmentation.asv
@@ -0,0 +1,41 @@
+function AddSegmentation(SegmentDataFolder, FolderDelimiter, BatchSize, ParFor_flag, IgnoreExisting_flag)
+if ParFor_flag
+ if isempty(gcp('nocreate'))
+ parpool;
+ end
+else
+ delete(gcp('nocreate'));
+end
+
+fprintf('Lung segmentation...\n');
+FileList = dir(SegmentDataFolder); FileList = FileList(3:end);
+FileList = FileList(~strcmp({FileList.name}, 'DatasetInfo.mat'));
+SampleNum = length(FileList);
+I_Mask = zeros(SampleNum, 1); I_BB = zeros(SampleNum, 1);
+tStart = tic; msgTxt = '';
+warned = false(1, SampleNum);
+if ParFor_flag
+ parfor j = 1:SampleNum
+ [I_Mask(j), I_BB(j), warned(j)] = LungSegmentation(sprintf('%s%s%s', SegmentDataFolder, FolderDelimiter, FileList(j).name), 'IgnoreExisting_flag', IgnoreExisting_flag);
+ tElapse = toc(tStart); tRemain = tElapse / eInd * (SampleNum - eInd);
+ if ~isempty(find(warned(sInd:eInd), 1))
+ msgPre = '';
+ else
+ msgPre = repmat('\b', 1, length(msgTxt) - 1);
+ end
+ msgTxt = sprintf('Progress (%d/%d): %.2f%%%%, %dmin %4.1fsec elapsed, %dmin %4.1fsec to go.\n', ...
+ eInd, SampleNum, eInd / SampleNum * 100, floor(tElapse / 60), mod(tElapse, 60), floor(tRemain / 60), mod(tRemain, 60));
+ fprintf([msgPre, msgTxt]);
+
+ end
+else
+ for j = 1:SampleNum
+ [I_Mask(j), I_BB(j), warned(j)] = LungSegmentation(sprintf('%s%s%s', SegmentDataFolder, FolderDelimiter, FileList(j).name), 'IgnoreExisting_flag', IgnoreExisting_flag);
+ end
+end
+
+
+fprintf('Average intensity in mask: %.2f\n', mean(I_Mask));
+fprintf('Average intensity in bounding box: %.2f\n', mean(I_BB));
+save(sprintf('%s%s%s', SegmentDataFolder, FolderDelimiter, 'DatasetInfo.mat'), 'I_Mask', 'I_BB','-v7');
+end
\ No newline at end of file
diff --git a/preprocessing/__init__.py b/preprocessing/__init__.py
new file mode 100644
index 0000000..9c31eaa
--- /dev/null
+++ b/preprocessing/__init__.py
@@ -0,0 +1 @@
+from full_prep import full_prep,savenpy
diff --git a/preprocessing/full_prep.py b/preprocessing/full_prep.py
new file mode 100644
index 0000000..d751600
--- /dev/null
+++ b/preprocessing/full_prep.py
@@ -0,0 +1,128 @@
+import os
+import numpy as np
+from scipy.io import loadmat
+import h5py
+from scipy.ndimage.interpolation import zoom
+from skimage import measure
+import warnings
+from scipy.ndimage.morphology import binary_dilation,generate_binary_structure
+from skimage.morphology import convex_hull_image
+from multiprocessing import Pool
+from functools import partial
+from step1 import step1_python
+import warnings
+
+def process_mask(mask):
+ convex_mask = np.copy(mask)
+ for i_layer in range(convex_mask.shape[0]):
+ mask1 = np.ascontiguousarray(mask[i_layer])
+ if np.sum(mask1)>0:
+ mask2 = convex_hull_image(mask1)
+ if np.sum(mask2)>2*np.sum(mask1):
+ mask2 = mask1
+ else:
+ mask2 = mask1
+ convex_mask[i_layer] = mask2
+ struct = generate_binary_structure(3,1)
+ dilatedMask = binary_dilation(convex_mask,structure=struct,iterations=10)
+ return dilatedMask
+
+# def savenpy(id):
+id = 1
+
+def lumTrans(img):
+ lungwin = np.array([-1200.,600.])
+ newimg = (img-lungwin[0])/(lungwin[1]-lungwin[0])
+ newimg[newimg<0]=0
+ newimg[newimg>1]=1
+ newimg = (newimg*255).astype('uint8')
+ return newimg
+
+def resample(imgs, spacing, new_spacing,order = 2):
+ if len(imgs.shape)==3:
+ new_shape = np.round(imgs.shape * spacing / new_spacing)
+ true_spacing = spacing * imgs.shape / new_shape
+ resize_factor = new_shape / imgs.shape
+ with warnings.catch_warnings():
+ warnings.simplefilter("ignore")
+ imgs = zoom(imgs, resize_factor, mode = 'nearest',order=order)
+ return imgs, true_spacing
+ elif len(imgs.shape)==4:
+ n = imgs.shape[-1]
+ newimg = []
+ for i in range(n):
+ slice = imgs[:,:,:,i]
+ newslice,true_spacing = resample(slice,spacing,new_spacing)
+ newimg.append(newslice)
+ newimg=np.transpose(np.array(newimg),[1,2,3,0])
+ return newimg,true_spacing
+ else:
+ raise ValueError('wrong shape')
+
+def savenpy(id,filelist,prep_folder,data_path,use_existing=True):
+ resolution = np.array([1,1,1])
+ name = filelist[id]
+ if use_existing:
+ if os.path.exists(os.path.join(prep_folder,name+'_label.npy')) and os.path.exists(os.path.join(prep_folder,name+'_clean.npy')):
+ print(name+' had been done')
+ return
+ try:
+ im, m1, m2, spacing = step1_python(os.path.join(data_path,name))
+ Mask = m1+m2
+
+ newshape = np.round(np.array(Mask.shape)*spacing/resolution)
+ xx,yy,zz= np.where(Mask)
+ box = np.array([[np.min(xx),np.max(xx)],[np.min(yy),np.max(yy)],[np.min(zz),np.max(zz)]])
+ box = box*np.expand_dims(spacing,1)/np.expand_dims(resolution,1)
+ box = np.floor(box).astype('int')
+ margin = 5
+ extendbox = np.vstack([np.max([[0,0,0],box[:,0]-margin],0),np.min([newshape,box[:,1]+2*margin],axis=0).T]).T
+ extendbox = extendbox.astype('int')
+
+
+
+ convex_mask = m1
+ dm1 = process_mask(m1)
+ dm2 = process_mask(m2)
+ dilatedMask = dm1+dm2
+ Mask = m1+m2
+ extramask = dilatedMask ^ Mask
+ bone_thresh = 210
+ pad_value = 170
+
+ im[np.isnan(im)]=-2000
+ sliceim = lumTrans(im)
+ sliceim = sliceim*dilatedMask+pad_value*(1-dilatedMask).astype('uint8')
+ bones = sliceim*extramask>bone_thresh
+ sliceim[bones] = pad_value
+ sliceim1,_ = resample(sliceim,spacing,resolution,order=1)
+ sliceim2 = sliceim1[extendbox[0,0]:extendbox[0,1],
+ extendbox[1,0]:extendbox[1,1],
+ extendbox[2,0]:extendbox[2,1]]
+ sliceim = sliceim2[np.newaxis,...]
+ np.save(os.path.join(prep_folder,name+'_clean'),sliceim)
+ np.save(os.path.join(prep_folder,name+'_label'),np.array([[0,0,0,0]]))
+ except:
+ print('bug in '+name)
+ raise
+ print(name+' done')
+
+
+def full_prep(data_path,prep_folder,n_worker = None,use_existing=True):
+ warnings.filterwarnings("ignore")
+ if not os.path.exists(prep_folder):
+ os.mkdir(prep_folder)
+
+
+ print('starting preprocessing')
+ pool = Pool(n_worker)
+ filelist = [f for f in os.listdir(data_path)]
+ partial_savenpy = partial(savenpy,filelist=filelist,prep_folder=prep_folder,
+ data_path=data_path,use_existing=use_existing)
+
+ N = len(filelist)
+ _=pool.map(partial_savenpy,range(N))
+ pool.close()
+ pool.join()
+ print('end preprocessing')
+ return filelist
diff --git a/preprocessing/step1.py b/preprocessing/step1.py
new file mode 100644
index 0000000..ae75cc5
--- /dev/null
+++ b/preprocessing/step1.py
@@ -0,0 +1,283 @@
+import numpy as np # linear algebra
+import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)
+import dicom
+import os
+import scipy.ndimage
+import matplotlib.pyplot as plt
+
+from skimage import measure, morphology
+
+
+
+def load_scan(path):
+ slices = [dicom.read_file(path + '/' + s) for s in os.listdir(path)]
+ slices.sort(key = lambda x: float(x.ImagePositionPatient[2]))
+ if slices[0].ImagePositionPatient[2] == slices[1].ImagePositionPatient[2]:
+ sec_num = 2;
+ while slices[0].ImagePositionPatient[2] == slices[sec_num].ImagePositionPatient[2]:
+ sec_num = sec_num+1;
+ slice_num = int(len(slices) / sec_num)
+ slices.sort(key = lambda x:float(x.InstanceNumber))
+ slices = slices[0:slice_num]
+ slices.sort(key = lambda x:float(x.ImagePositionPatient[2]))
+ try:
+ slice_thickness = np.abs(slices[0].ImagePositionPatient[2] - slices[1].ImagePositionPatient[2])
+ except:
+ slice_thickness = np.abs(slices[0].SliceLocation - slices[1].SliceLocation)
+
+ for s in slices:
+ s.SliceThickness = slice_thickness
+
+ return slices
+
+def get_pixels_hu(slices):
+ image = np.stack([s.pixel_array for s in slices])
+ # Convert to int16 (from sometimes int16),
+ # should be possible as values should always be low enough (<32k)
+ image = image.astype(np.int16)
+
+ # Convert to Hounsfield units (HU)
+ for slice_number in range(len(slices)):
+ intercept = slices[slice_number].RescaleIntercept
+ slope = slices[slice_number].RescaleSlope
+
+ if slope != 1:
+ image[slice_number] = slope * image[slice_number].astype(np.float64)
+ image[slice_number] = image[slice_number].astype(np.int16)
+
+ image[slice_number] += np.int16(intercept)
+
+ return np.array(image, dtype=np.int16), np.array([slices[0].SliceThickness] + slices[0].PixelSpacing, dtype=np.float32)
+
+def binarize_per_slice(image, spacing, intensity_th=-600, sigma=1, area_th=30, eccen_th=0.99, bg_patch_size=10):
+ bw = np.zeros(image.shape, dtype=bool)
+
+ # prepare a mask, with all corner values set to nan
+ image_size = image.shape[1]
+ grid_axis = np.linspace(-image_size/2+0.5, image_size/2-0.5, image_size)
+ x, y = np.meshgrid(grid_axis, grid_axis)
+ d = (x**2+y**2)**0.5
+ nan_mask = (d area_th and prop.eccentricity < eccen_th:
+ valid_label.add(prop.label)
+ current_bw = np.in1d(label, list(valid_label)).reshape(label.shape)
+ bw[i] = current_bw
+
+ return bw
+
+def all_slice_analysis(bw, spacing, cut_num=0, vol_limit=[0.68, 8.2], area_th=6e3, dist_th=62):
+ # in some cases, several top layers need to be removed first
+ if cut_num > 0:
+ bw0 = np.copy(bw)
+ bw[-cut_num:] = False
+ label = measure.label(bw, connectivity=1)
+ # remove components access to corners
+ mid = int(label.shape[2] / 2)
+ bg_label = set([label[0, 0, 0], label[0, 0, -1], label[0, -1, 0], label[0, -1, -1], \
+ label[-1-cut_num, 0, 0], label[-1-cut_num, 0, -1], label[-1-cut_num, -1, 0], label[-1-cut_num, -1, -1], \
+ label[0, 0, mid], label[0, -1, mid], label[-1-cut_num, 0, mid], label[-1-cut_num, -1, mid]])
+ for l in bg_label:
+ label[label == l] = 0
+
+ # select components based on volume
+ properties = measure.regionprops(label)
+ for prop in properties:
+ if prop.area * spacing.prod() < vol_limit[0] * 1e6 or prop.area * spacing.prod() > vol_limit[1] * 1e6:
+ label[label == prop.label] = 0
+
+ # prepare a distance map for further analysis
+ x_axis = np.linspace(-label.shape[1]/2+0.5, label.shape[1]/2-0.5, label.shape[1]) * spacing[1]
+ y_axis = np.linspace(-label.shape[2]/2+0.5, label.shape[2]/2-0.5, label.shape[2]) * spacing[2]
+ x, y = np.meshgrid(x_axis, y_axis)
+ d = (x**2+y**2)**0.5
+ vols = measure.regionprops(label)
+ valid_label = set()
+ # select components based on their area and distance to center axis on all slices
+ for vol in vols:
+ single_vol = label == vol.label
+ slice_area = np.zeros(label.shape[0])
+ min_distance = np.zeros(label.shape[0])
+ for i in range(label.shape[0]):
+ slice_area[i] = np.sum(single_vol[i]) * np.prod(spacing[1:3])
+ min_distance[i] = np.min(single_vol[i] * d + (1 - single_vol[i]) * np.max(d))
+
+ if np.average([min_distance[i] for i in range(label.shape[0]) if slice_area[i] > area_th]) < dist_th:
+ valid_label.add(vol.label)
+
+ bw = np.in1d(label, list(valid_label)).reshape(label.shape)
+
+ # fill back the parts removed earlier
+ if cut_num > 0:
+ # bw1 is bw with removed slices, bw2 is a dilated version of bw, part of their intersection is returned as final mask
+ bw1 = np.copy(bw)
+ bw1[-cut_num:] = bw0[-cut_num:]
+ bw2 = np.copy(bw)
+ bw2 = scipy.ndimage.binary_dilation(bw2, iterations=cut_num)
+ bw3 = bw1 & bw2
+ label = measure.label(bw, connectivity=1)
+ label3 = measure.label(bw3, connectivity=1)
+ l_list = list(set(np.unique(label)) - {0})
+ valid_l3 = set()
+ for l in l_list:
+ indices = np.nonzero(label==l)
+ l3 = label3[indices[0][0], indices[1][0], indices[2][0]]
+ if l3 > 0:
+ valid_l3.add(l3)
+ bw = np.in1d(label3, list(valid_l3)).reshape(label3.shape)
+
+ return bw, len(valid_label)
+
+def fill_hole(bw):
+ # fill 3d holes
+ label = measure.label(~bw)
+ # idendify corner components
+ bg_label = set([label[0, 0, 0], label[0, 0, -1], label[0, -1, 0], label[0, -1, -1], \
+ label[-1, 0, 0], label[-1, 0, -1], label[-1, -1, 0], label[-1, -1, -1]])
+ bw = ~np.in1d(label, list(bg_label)).reshape(label.shape)
+
+ return bw
+
+
+
+
+def two_lung_only(bw, spacing, max_iter=22, max_ratio=4.8):
+ def extract_main(bw, cover=0.95):
+ for i in range(bw.shape[0]):
+ current_slice = bw[i]
+ label = measure.label(current_slice)
+ properties = measure.regionprops(label)
+ properties.sort(key=lambda x: x.area, reverse=True)
+ area = [prop.area for prop in properties]
+ count = 0
+ sum = 0
+ while sum < np.sum(area)*cover:
+ sum = sum+area[count]
+ count = count+1
+ filter = np.zeros(current_slice.shape, dtype=bool)
+ for j in range(count):
+ bb = properties[j].bbox
+ filter[bb[0]:bb[2], bb[1]:bb[3]] = filter[bb[0]:bb[2], bb[1]:bb[3]] | properties[j].convex_image
+ bw[i] = bw[i] & filter
+
+ label = measure.label(bw)
+ properties = measure.regionprops(label)
+ properties.sort(key=lambda x: x.area, reverse=True)
+ bw = label==properties[0].label
+
+ return bw
+
+ def fill_2d_hole(bw):
+ for i in range(bw.shape[0]):
+ current_slice = bw[i]
+ label = measure.label(current_slice)
+ properties = measure.regionprops(label)
+ for prop in properties:
+ bb = prop.bbox
+ current_slice[bb[0]:bb[2], bb[1]:bb[3]] = current_slice[bb[0]:bb[2], bb[1]:bb[3]] | prop.filled_image
+ bw[i] = current_slice
+
+ return bw
+
+ found_flag = False
+ iter_count = 0
+ bw0 = np.copy(bw)
+ while not found_flag and iter_count < max_iter:
+ label = measure.label(bw, connectivity=2)
+ properties = measure.regionprops(label)
+ properties.sort(key=lambda x: x.area, reverse=True)
+ if len(properties) > 1 and properties[0].area/properties[1].area < max_ratio:
+ found_flag = True
+ bw1 = label == properties[0].label
+ bw2 = label == properties[1].label
+ else:
+ bw = scipy.ndimage.binary_erosion(bw)
+ iter_count = iter_count + 1
+
+ if found_flag:
+ d1 = scipy.ndimage.morphology.distance_transform_edt(bw1 == False, sampling=spacing)
+ d2 = scipy.ndimage.morphology.distance_transform_edt(bw2 == False, sampling=spacing)
+ bw1 = bw0 & (d1 < d2)
+ bw2 = bw0 & (d1 > d2)
+
+ bw1 = extract_main(bw1)
+ bw2 = extract_main(bw2)
+
+ else:
+ bw1 = bw0
+ bw2 = np.zeros(bw.shape).astype('bool')
+
+ bw1 = fill_2d_hole(bw1)
+ bw2 = fill_2d_hole(bw2)
+ bw = bw1 | bw2
+
+ return bw1, bw2, bw
+
+def step1_python(case_path):
+ case = load_scan(case_path)
+ case_pixels, spacing = get_pixels_hu(case)
+ bw = binarize_per_slice(case_pixels, spacing)
+ flag = 0
+ cut_num = 0
+ cut_step = 2
+ bw0 = np.copy(bw)
+ while flag == 0 and cut_num < bw.shape[0]:
+ bw = np.copy(bw0)
+ bw, flag = all_slice_analysis(bw, spacing, cut_num=cut_num, vol_limit=[0.68,7.5])
+ cut_num = cut_num + cut_step
+
+ bw = fill_hole(bw)
+ bw1, bw2, bw = two_lung_only(bw, spacing)
+ return case_pixels, bw1, bw2, spacing
+
+if __name__ == '__main__':
+ INPUT_FOLDER = '/work/DataBowl3/stage1/stage1/'
+ patients = os.listdir(INPUT_FOLDER)
+ patients.sort()
+ case_pixels, m1, m2, spacing = step1_python(os.path.join(INPUT_FOLDER,patients[25]))
+ plt.imshow(m1[60])
+ plt.figure()
+ plt.imshow(m2[60])
+# first_patient = load_scan(INPUT_FOLDER + patients[25])
+# first_patient_pixels, spacing = get_pixels_hu(first_patient)
+# plt.hist(first_patient_pixels.flatten(), bins=80, color='c')
+# plt.xlabel("Hounsfield Units (HU)")
+# plt.ylabel("Frequency")
+# plt.show()
+
+# # Show some slice in the middle
+# h = 80
+# plt.imshow(first_patient_pixels[h], cmap=plt.cm.gray)
+# plt.show()
+
+# bw = binarize_per_slice(first_patient_pixels, spacing)
+# plt.imshow(bw[h], cmap=plt.cm.gray)
+# plt.show()
+
+# flag = 0
+# cut_num = 0
+# while flag == 0:
+# bw, flag = all_slice_analysis(bw, spacing, cut_num=cut_num)
+# cut_num = cut_num + 1
+# plt.imshow(bw[h], cmap=plt.cm.gray)
+# plt.show()
+
+# bw = fill_hole(bw)
+# plt.imshow(bw[h], cmap=plt.cm.gray)
+# plt.show()
+
+# bw1, bw2, bw = two_lung_only(bw, spacing)
+# plt.imshow(bw[h], cmap=plt.cm.gray)
+# plt.show()
diff --git a/split_combine.py b/split_combine.py
new file mode 100644
index 0000000..d4b5b49
--- /dev/null
+++ b/split_combine.py
@@ -0,0 +1,100 @@
+import torch
+import numpy as np
+class SplitComb():
+ def __init__(self,side_len,max_stride,stride,margin,pad_value):
+ self.side_len = side_len
+ self.max_stride = max_stride
+ self.stride = stride
+ self.margin = margin
+ self.pad_value = pad_value
+
+ def split(self, data, side_len = None, max_stride = None, margin = None):
+ if side_len==None:
+ side_len = self.side_len
+ if max_stride == None:
+ max_stride = self.max_stride
+ if margin == None:
+ margin = self.margin
+
+ assert(side_len > margin)
+ assert(side_len % max_stride == 0)
+ assert(margin % max_stride == 0)
+
+ splits = []
+ _, z, h, w = data.shape
+
+ nz = int(np.ceil(float(z) / side_len))
+ nh = int(np.ceil(float(h) / side_len))
+ nw = int(np.ceil(float(w) / side_len))
+
+ nzhw = [nz,nh,nw]
+ self.nzhw = nzhw
+
+ pad = [ [0, 0],
+ [margin, nz * side_len - z + margin],
+ [margin, nh * side_len - h + margin],
+ [margin, nw * side_len - w + margin]]
+ data = np.pad(data, pad, 'edge')
+
+ for iz in range(nz):
+ for ih in range(nh):
+ for iw in range(nw):
+ sz = iz * side_len
+ ez = (iz + 1) * side_len + 2 * margin
+ sh = ih * side_len
+ eh = (ih + 1) * side_len + 2 * margin
+ sw = iw * side_len
+ ew = (iw + 1) * side_len + 2 * margin
+
+ split = data[np.newaxis, :, sz:ez, sh:eh, sw:ew]
+ splits.append(split)
+
+ splits = np.concatenate(splits, 0)
+ return splits,nzhw
+
+ def combine(self, output, nzhw = None, side_len=None, stride=None, margin=None):
+
+ if side_len==None:
+ side_len = self.side_len
+ if stride == None:
+ stride = self.stride
+ if margin == None:
+ margin = self.margin
+ if nzhw==None:
+ nz = self.nz
+ nh = self.nh
+ nw = self.nw
+ else:
+ nz,nh,nw = nzhw
+ assert(side_len % stride == 0)
+ assert(margin % stride == 0)
+ side_len /= stride
+ margin /= stride
+
+ splits = []
+ for i in range(len(output)):
+ splits.append(output[i])
+
+ output = -1000000 * np.ones((
+ nz * side_len,
+ nh * side_len,
+ nw * side_len,
+ splits[0].shape[3],
+ splits[0].shape[4]), np.float32)
+
+ idx = 0
+ for iz in range(nz):
+ for ih in range(nh):
+ for iw in range(nw):
+ sz = iz * side_len
+ ez = (iz + 1) * side_len
+ sh = ih * side_len
+ eh = (ih + 1) * side_len
+ sw = iw * side_len
+ ew = (iw + 1) * side_len
+
+ split = splits[idx][margin:margin + side_len, margin:margin + side_len, margin:margin + side_len]
+ output[sz:ez, sh:eh, sw:ew] = split
+ idx += 1
+
+ return output
diff --git a/test_classifier.py b/test_classifier.py
new file mode 100644
index 0000000..e69de29
diff --git a/test_detect.py b/test_detect.py
new file mode 100644
index 0000000..70163a0
--- /dev/null
+++ b/test_detect.py
@@ -0,0 +1,77 @@
+import argparse
+import os
+import time
+import numpy as np
+from importlib import import_module
+import shutil
+from utils import *
+import sys
+from split_combine import SplitComb
+
+import torch
+from torch.nn import DataParallel
+from torch.backends import cudnn
+from torch.utils.data import DataLoader
+from torch import optim
+from torch.autograd import Variable
+
+from layers import acc
+
+def test_detect(data_loader, net, get_pbb, save_dir, config,n_gpu):
+ start_time = time.time()
+ net.eval()
+ split_comber = data_loader.dataset.split_comber
+ for i_name, (data, target, coord, nzhw) in enumerate(data_loader):
+ s = time.time()
+ target = [np.asarray(t, np.float32) for t in target]
+ lbb = target[0]
+ nzhw = nzhw[0]
+ name = data_loader.dataset.filenames[i_name].split('-')[0].split('/')[-1]
+ shortname = name.split('_clean')[0]
+ data = data[0][0]
+ coord = coord[0][0]
+ isfeat = False
+ if 'output_feature' in config:
+ if config['output_feature']:
+ isfeat = True
+ n_per_run = n_gpu
+ print(data.size())
+ splitlist = range(0,len(data)+1,n_gpu)
+ if splitlist[-1]!=len(data):
+ splitlist.append(len(data))
+ outputlist = []
+ featurelist = []
+
+ for i in range(len(splitlist)-1):
+ input = Variable(data[splitlist[i]:splitlist[i+1]], volatile = True).cuda()
+ inputcoord = Variable(coord[splitlist[i]:splitlist[i+1]], volatile = True).cuda()
+ if isfeat:
+ output,feature = net(input,inputcoord)
+ featurelist.append(feature.data.cpu().numpy())
+ else:
+ output = net(input,inputcoord)
+ outputlist.append(output.data.cpu().numpy())
+ output = np.concatenate(outputlist,0)
+ output = split_comber.combine(output,nzhw=nzhw)
+ if isfeat:
+ feature = np.concatenate(featurelist,0).transpose([0,2,3,4,1])[:,:,:,:,:,np.newaxis]
+ feature = split_comber.combine(feature,sidelen)[...,0]
+
+ thresh = -3
+ pbb,mask = get_pbb(output,thresh,ismask=True)
+ if isfeat:
+ feature_selected = feature[mask[0],mask[1],mask[2]]
+ np.save(os.path.join(save_dir, shortname+'_feature.npy'), feature_selected)
+ #tp,fp,fn,_ = acc(pbb,lbb,0,0.1,0.1)
+ #print([len(tp),len(fp),len(fn)])
+ print([i_name,shortname])
+ e = time.time()
+
+ np.save(os.path.join(save_dir, shortname+'_pbb.npy'), pbb)
+ np.save(os.path.join(save_dir, shortname+'_lbb.npy'), lbb)
+ end_time = time.time()
+
+
+ print('elapsed time is %3.2f seconds' % (end_time - start_time))
+ print
+ print
diff --git a/training/classifier/adapt_ckpt.py b/training/classifier/adapt_ckpt.py
new file mode 100644
index 0000000..c2361e1
--- /dev/null
+++ b/training/classifier/adapt_ckpt.py
@@ -0,0 +1,29 @@
+import torch
+import numpy as np
+import argparse
+from importlib import import_module
+parser = argparse.ArgumentParser(description='network surgery')
+parser.add_argument('--model1', '-m1', metavar='MODEL', default='base',
+ help='model')
+parser.add_argument('--model2', '-m2', metavar='MODEL', default='base',
+ help='model')
+parser.add_argument('--resume', default='', type=str, metavar='PATH',
+ help='path to latest checkpoint (default: none)')
+# args = parser.parse_args(['--model1','net_detector_3','--model2','net_classifier_3','--resume','../detector/results/res18-20170419-153425/020.ckpt'])
+args = parser.parse_args()
+
+nodmodel = import_module(args.model1)
+config1, nod_net, loss, get_pbb = nodmodel.get_model()
+checkpoint = torch.load(args.resume)
+state_dict = checkpoint['state_dict']
+nod_net.load_state_dict(state_dict)
+
+casemodel = import_module(args.model2)
+
+config2 = casemodel.config
+args.lr_stage2 = config2['lr_stage']
+args.lr_preset2 = config2['lr']
+topk = config2['topk']
+case_net = casemodel.CaseNet(topk = topk,nodulenet=nod_net)
+new_state_dict = case_net.state_dict()
+torch.save({'state_dict': new_state_dict,'epoch':0},'results/start.ckpt')
diff --git a/training/classifier/data_classifier.py b/training/classifier/data_classifier.py
new file mode 100644
index 0000000..d8335c9
--- /dev/null
+++ b/training/classifier/data_classifier.py
@@ -0,0 +1,218 @@
+import numpy as np
+import torch
+from torch.utils.data import Dataset
+import os
+import time
+import collections
+import random
+from layers import iou
+from scipy.ndimage import zoom
+import warnings
+from scipy.ndimage.interpolation import rotate
+from layers import nms,iou
+import pandas
+
+class DataBowl3Classifier(Dataset):
+ def __init__(self, split, config, phase = 'train'):
+ assert(phase == 'train' or phase == 'val' or phase == 'test')
+
+ self.random_sample = config['random_sample']
+ self.T = config['T']
+ self.topk = config['topk']
+ self.crop_size = config['crop_size']
+ self.stride = config['stride']
+ self.augtype = config['augtype']
+ #self.labels = np.array(pandas.read_csv(config['labelfile']))
+
+ datadir = config['datadir']
+ bboxpath = config['bboxpath']
+ self.phase = phase
+ self.candidate_box = []
+ self.pbb_label = []
+
+ idcs = split
+ self.filenames = [os.path.join(datadir, '%s_clean.npy' % idx) for idx in idcs]
+ labels = np.array(pandas.read_csv(config['labelfile']))
+ if phase !='test':
+ self.yset = np.array([labels[labels[:,0]==f.split('-')[0].split('_')[0],1] for f in split]).astype('int')
+ idcs = [f.split('-')[0] for f in idcs]
+
+
+ for idx in idcs:
+ pbb = np.load(os.path.join(bboxpath,idx+'_pbb.npy'))
+ pbb = pbb[pbb[:,0]>config['conf_th']]
+ pbb = nms(pbb, config['nms_th'])
+
+ lbb = np.load(os.path.join(bboxpath,idx+'_lbb.npy'))
+ pbb_label = []
+
+ for p in pbb:
+ isnod = False
+ for l in lbb:
+ score = iou(p[1:5], l)
+ if score > config['detect_th']:
+ isnod = True
+ break
+ pbb_label.append(isnod)
+# if idx.startswith()
+ self.candidate_box.append(pbb)
+ self.pbb_label.append(np.array(pbb_label))
+ self.crop = simpleCrop(config,phase)
+
+
+ def __getitem__(self, idx,split=None):
+ t = time.time()
+ np.random.seed(int(str(t%1)[2:7]))#seed according to time
+
+ pbb = self.candidate_box[idx]
+ pbb_label = self.pbb_label[idx]
+ conf_list = pbb[:,0]
+ T = self.T
+ topk = self.topk
+ img = np.load(self.filenames[idx])
+ if self.random_sample and self.phase=='train':
+ chosenid = sample(conf_list,topk,T=T)
+ #chosenid = conf_list.argsort()[::-1][:topk]
+ else:
+ chosenid = conf_list.argsort()[::-1][:topk]
+ croplist = np.zeros([topk,1,self.crop_size[0],self.crop_size[1],self.crop_size[2]]).astype('float32')
+ coordlist = np.zeros([topk,3,self.crop_size[0]/self.stride,self.crop_size[1]/self.stride,self.crop_size[2]/self.stride]).astype('float32')
+ padmask = np.concatenate([np.ones(len(chosenid)),np.zeros(self.topk-len(chosenid))])
+ isnodlist = np.zeros([topk])
+
+
+ for i,id in enumerate(chosenid):
+ target = pbb[id,1:]
+ isnod = pbb_label[id]
+ crop,coord = self.crop(img,target)
+ if self.phase=='train':
+ crop,coord = augment(crop,coord,
+ ifflip=self.augtype['flip'],ifrotate=self.augtype['rotate'],
+ ifswap = self.augtype['swap'])
+ crop = crop.astype(np.float32)
+ croplist[i] = crop
+ coordlist[i] = coord
+ isnodlist[i] = isnod
+
+ if self.phase!='test':
+ y = np.array([self.yset[idx]])
+ return torch.from_numpy(croplist).float(), torch.from_numpy(coordlist).float(), torch.from_numpy(isnodlist).int(), torch.from_numpy(y)
+ else:
+ return torch.from_numpy(croplist).float(), torch.from_numpy(coordlist).float(), torch.from_numpy(isnodlist).int()
+ def __len__(self):
+ if self.phase != 'test':
+ return len(self.candidate_box)
+ else:
+ return len(self.candidate_box)
+
+
+
+class simpleCrop():
+ def __init__(self,config,phase):
+ self.crop_size = config['crop_size']
+ self.scaleLim = config['scaleLim']
+ self.radiusLim = config['radiusLim']
+ self.jitter_range = config['jitter_range']
+ self.isScale = config['augtype']['scale'] and phase=='train'
+ self.stride = config['stride']
+ self.filling_value = config['filling_value']
+ self.phase = phase
+
+ def __call__(self,imgs,target):
+ if self.isScale:
+ radiusLim = self.radiusLim
+ scaleLim = self.scaleLim
+ scaleRange = [np.min([np.max([(radiusLim[0]/target[3]),scaleLim[0]]),1])
+ ,np.max([np.min([(radiusLim[1]/target[3]),scaleLim[1]]),1])]
+ scale = np.random.rand()*(scaleRange[1]-scaleRange[0])+scaleRange[0]
+ crop_size = (np.array(self.crop_size).astype('float')/scale).astype('int')
+ else:
+ crop_size = np.array(self.crop_size).astype('int')
+ if self.phase=='train':
+ jitter_range = target[3]*self.jitter_range
+ jitter = (np.random.rand(3)-0.5)*jitter_range
+ else:
+ jitter = 0
+ start = (target[:3]- crop_size/2 + jitter).astype('int')
+ pad = [[0,0]]
+ for i in range(3):
+ if start[i]<0:
+ leftpad = -start[i]
+ start[i] = 0
+ else:
+ leftpad = 0
+ if start[i]+crop_size[i]>imgs.shape[i+1]:
+ rightpad = start[i]+crop_size[i]-imgs.shape[i+1]
+ else:
+ rightpad = 0
+ pad.append([leftpad,rightpad])
+ imgs = np.pad(imgs,pad,'constant',constant_values =self.filling_value)
+ crop = imgs[:,start[0]:start[0]+crop_size[0],start[1]:start[1]+crop_size[1],start[2]:start[2]+crop_size[2]]
+
+ normstart = np.array(start).astype('float32')/np.array(imgs.shape[1:])-0.5
+ normsize = np.array(crop_size).astype('float32')/np.array(imgs.shape[1:])
+ xx,yy,zz = np.meshgrid(np.linspace(normstart[0],normstart[0]+normsize[0],self.crop_size[0]/self.stride),
+ np.linspace(normstart[1],normstart[1]+normsize[1],self.crop_size[1]/self.stride),
+ np.linspace(normstart[2],normstart[2]+normsize[2],self.crop_size[2]/self.stride),indexing ='ij')
+ coord = np.concatenate([xx[np.newaxis,...], yy[np.newaxis,...],zz[np.newaxis,:]],0).astype('float32')
+
+ if self.isScale:
+ with warnings.catch_warnings():
+ warnings.simplefilter("ignore")
+ crop = zoom(crop,[1,scale,scale,scale],order=1)
+ newpad = self.crop_size[0]-crop.shape[1:][0]
+ if newpad<0:
+ crop = crop[:,:-newpad,:-newpad,:-newpad]
+ elif newpad>0:
+ pad2 = [[0,0],[0,newpad],[0,newpad],[0,newpad]]
+ crop = np.pad(crop,pad2,'constant',constant_values =self.filling_value)
+
+ return crop,coord
+
+def sample(conf,N,T=1):
+ if len(conf)>N:
+ target = range(len(conf))
+ chosen_list = []
+ for i in range(N):
+ chosenidx = sampleone(target,conf,T)
+ chosen_list.append(target[chosenidx])
+ target.pop(chosenidx)
+ conf = np.delete(conf, chosenidx)
+
+
+ return chosen_list
+ else:
+ return np.arange(len(conf))
+
+def sampleone(target,conf,T):
+ assert len(conf)>1
+ p = softmax(conf/T)
+ p = np.max([np.ones_like(p)*0.00001,p],axis=0)
+ p = p/np.sum(p)
+ return np.random.choice(np.arange(len(target)),size=1,replace = False, p=p)[0]
+
+def softmax(x):
+ maxx = np.max(x)
+ return np.exp(x-maxx)/np.sum(np.exp(x-maxx))
+
+
+def augment(sample, coord, ifflip = True, ifrotate=True, ifswap = True):
+ # angle1 = np.random.rand()*180
+ if ifrotate:
+ validrot = False
+ counter = 0
+ angle1 = np.random.rand()*180
+ size = np.array(sample.shape[2:4]).astype('float')
+ rotmat = np.array([[np.cos(angle1/180*np.pi),-np.sin(angle1/180*np.pi)],[np.sin(angle1/180*np.pi),np.cos(angle1/180*np.pi)]])
+ sample = rotate(sample,angle1,axes=(2,3),reshape=False)
+ if ifswap:
+ if sample.shape[1]==sample.shape[2] and sample.shape[1]==sample.shape[3]:
+ axisorder = np.random.permutation(3)
+ sample = np.transpose(sample,np.concatenate([[0],axisorder+1]))
+ coord = np.transpose(coord,np.concatenate([[0],axisorder+1]))
+
+ if ifflip:
+ flipid = np.array([np.random.randint(2),np.random.randint(2),np.random.randint(2)])*2-1
+ sample = np.ascontiguousarray(sample[:,::flipid[0],::flipid[1],::flipid[2]])
+ coord = np.ascontiguousarray(coord[:,::flipid[0],::flipid[1],::flipid[2]])
+ return sample, coord
diff --git a/training/classifier/data_detector.py b/training/classifier/data_detector.py
new file mode 100644
index 0000000..199c69b
--- /dev/null
+++ b/training/classifier/data_detector.py
@@ -0,0 +1,406 @@
+import numpy as np
+import torch
+from torch.utils.data import Dataset
+import os
+import time
+import collections
+import random
+from layers import iou
+from scipy.ndimage import zoom
+import warnings
+from scipy.ndimage.interpolation import rotate
+from scipy.ndimage.morphology import binary_dilation,generate_binary_structure
+
+class DataBowl3Detector(Dataset):
+ def __init__(self, split, config, phase = 'train',split_comber=None):
+ assert(phase == 'train' or phase == 'val' or phase == 'test')
+ self.phase = phase
+ self.max_stride = config['max_stride']
+ self.stride = config['stride']
+ sizelim = config['sizelim']/config['reso']
+ sizelim2 = config['sizelim2']/config['reso']
+ sizelim3 = config['sizelim3']/config['reso']
+ self.blacklist = config['blacklist']
+ self.isScale = config['aug_scale']
+ self.r_rand = config['r_rand_crop']
+ self.augtype = config['augtype']
+ data_dir = config['datadir']
+ self.pad_value = config['pad_value']
+
+ self.split_comber = split_comber
+ idcs = split
+ if phase!='test':
+ idcs = [f for f in idcs if f not in self.blacklist]
+
+ self.filenames = [os.path.join(data_dir, '%s_clean.npy' % idx) for idx in idcs]
+ self.kagglenames = [f for f in self.filenames if len(f.split('/')[-1].split('_')[0])>20]
+ self.lunanames = [f for f in self.filenames if len(f.split('/')[-1].split('_')[0])<20]
+
+ labels = []
+
+ for idx in idcs:
+ l = np.load(os.path.join(data_dir, '%s_label.npy' %idx))
+ if np.all(l==0):
+ l=np.array([])
+ labels.append(l)
+
+ self.sample_bboxes = labels
+
+ self.bboxes = []
+ for i, l in enumerate(labels):
+ if len(l) > 0 :
+ for t in l:
+ if t[3]>sizelim:
+ self.bboxes.append([np.concatenate([[i],t])])
+ if t[3]>sizelim2:
+ self.bboxes+=[[np.concatenate([[i],t])]]*2
+ if t[3]>sizelim3:
+ self.bboxes+=[[np.concatenate([[i],t])]]*4
+ if len(self.bboxes)>0:
+ self.bboxes = np.concatenate(self.bboxes,axis = 0)
+ else:
+ self.bboxes = np.array(self.bboxes)
+ self.crop = Crop(config)
+ self.label_mapping = LabelMapping(config, self.phase)
+
+ def __getitem__(self, idx,split=None):
+ t = time.time()
+ np.random.seed(int(str(t%1)[2:7]))#seed according to time
+
+ isRandomImg = False
+ if self.phase !='test':
+ if idx>=len(self.bboxes):
+ isRandom = True
+ idx = idx%len(self.bboxes)
+ isRandomImg = np.random.randint(2)
+ else:
+ isRandom = False
+ else:
+ isRandom = False
+
+ if self.phase != 'test':
+ if not isRandomImg:
+ bbox = self.bboxes[idx]
+ filename = self.filenames[int(bbox[0])]
+ imgs = np.load(filename)
+ bboxes = self.sample_bboxes[int(bbox[0])]
+ isScale = self.augtype['scale'] and (self.phase=='train')
+ sample, target, bboxes, coord = self.crop(imgs, bbox[1:], bboxes,isScale,isRandom)
+ if self.phase=='train' and not isRandom:
+ sample, target, bboxes, coord = augment(sample, target, bboxes, coord,
+ ifflip = self.augtype['flip'], ifrotate=self.augtype['rotate'], ifswap = self.augtype['swap'])
+ else:
+ randimid = np.random.randint(len(self.kagglenames))
+ filename = self.kagglenames[randimid]
+ imgs = np.load(filename)
+ bboxes = self.sample_bboxes[randimid]
+ isScale = self.augtype['scale'] and (self.phase=='train')
+ sample, target, bboxes, coord = self.crop(imgs, [], bboxes,isScale=False,isRand=True)
+ label = self.label_mapping(sample.shape[1:], target, bboxes)
+ sample = sample.astype(np.float32)
+ #if filename in self.kagglenames:
+ # label[label==-1]=0
+ return torch.from_numpy(sample), torch.from_numpy(label), coord
+ else:
+ imgs = np.load(self.filenames[idx])
+ bboxes = self.sample_bboxes[idx]
+ nz, nh, nw = imgs.shape[1:]
+ pz = int(np.ceil(float(nz) / self.stride)) * self.stride
+ ph = int(np.ceil(float(nh) / self.stride)) * self.stride
+ pw = int(np.ceil(float(nw) / self.stride)) * self.stride
+ imgs = np.pad(imgs, [[0,0],[0, pz - nz], [0, ph - nh], [0, pw - nw]], 'constant',constant_value = self.pad_value)
+ xx,yy,zz = np.meshgrid(np.linspace(-0.5,0.5,imgs.shape[1]/self.stride),
+ np.linspace(-0.5,0.5,imgs.shape[2]/self.stride),
+ np.linspace(-0.5,0.5,imgs.shape[3]/self.stride),indexing ='ij')
+ coord = np.concatenate([xx[np.newaxis,...], yy[np.newaxis,...],zz[np.newaxis,:]],0).astype('float32')
+ imgs, nzhw = self.split_comber.split(imgs)
+ coord2, nzhw2 = self.split_comber.split(coord,
+ side_len = self.split_comber.side_len/self.stride,
+ max_stride = self.split_comber.max_stride/self.stride,
+ margin = self.split_comber.margin/self.stride)
+ assert np.all(nzhw==nzhw2)
+ return torch.from_numpy(imgs), bboxes, torch.from_numpy(coord2), np.array(nzhw)
+
+ def __len__(self):
+ if self.phase == 'train':
+ return len(self.bboxes)/(1-self.r_rand)
+ elif self.phase =='val':
+ return len(self.bboxes)
+ else:
+ return len(self.sample_bboxes)
+
+
+def augment(sample, target, bboxes, coord, ifflip = True, ifrotate=True, ifswap = True):
+ # angle1 = np.random.rand()*180
+ if ifrotate:
+ validrot = False
+ counter = 0
+ while not validrot:
+ newtarget = np.copy(target)
+ angle1 = (np.random.rand()-0.5)*20
+ size = np.array(sample.shape[2:4]).astype('float')
+ rotmat = np.array([[np.cos(angle1/180*np.pi),-np.sin(angle1/180*np.pi)],[np.sin(angle1/180*np.pi),np.cos(angle1/180*np.pi)]])
+ newtarget[1:3] = np.dot(rotmat,target[1:3]-size/2)+size/2
+ if np.all(newtarget[:3]>target[3]) and np.all(newtarget[:3]< np.array(sample.shape[1:4])-newtarget[3]):
+ validrot = True
+ target = newtarget
+ sample = rotate(sample,angle1,axes=(2,3),reshape=False)
+ coord = rotate(coord,angle1,axes=(2,3),reshape=False)
+ for box in bboxes:
+ box[1:3] = np.dot(rotmat,box[1:3]-size/2)+size/2
+ else:
+ counter += 1
+ if counter ==3:
+ break
+ if ifswap:
+ if sample.shape[1]==sample.shape[2] and sample.shape[1]==sample.shape[3]:
+ axisorder = np.random.permutation(3)
+ sample = np.transpose(sample,np.concatenate([[0],axisorder+1]))
+ coord = np.transpose(coord,np.concatenate([[0],axisorder+1]))
+ target[:3] = target[:3][axisorder]
+ bboxes[:,:3] = bboxes[:,:3][:,axisorder]
+
+ if ifflip:
+# flipid = np.array([np.random.randint(2),np.random.randint(2),np.random.randint(2)])*2-1
+ flipid = np.array([1,np.random.randint(2),np.random.randint(2)])*2-1
+ sample = np.ascontiguousarray(sample[:,::flipid[0],::flipid[1],::flipid[2]])
+ coord = np.ascontiguousarray(coord[:,::flipid[0],::flipid[1],::flipid[2]])
+ for ax in range(3):
+ if flipid[ax]==-1:
+ target[ax] = np.array(sample.shape[ax+1])-target[ax]
+ bboxes[:,ax]= np.array(sample.shape[ax+1])-bboxes[:,ax]
+ return sample, target, bboxes, coord
+
+class Crop(object):
+ def __init__(self, config):
+ self.crop_size = config['crop_size']
+ self.bound_size = config['bound_size']
+ self.stride = config['stride']
+ self.pad_value = config['pad_value']
+
+ def __call__(self, imgs, target, bboxes,isScale=False,isRand=False):
+ if isScale:
+ radiusLim = [8.,100.]
+ scaleLim = [0.75,1.25]
+ scaleRange = [np.min([np.max([(radiusLim[0]/target[3]),scaleLim[0]]),1])
+ ,np.max([np.min([(radiusLim[1]/target[3]),scaleLim[1]]),1])]
+ scale = np.random.rand()*(scaleRange[1]-scaleRange[0])+scaleRange[0]
+ crop_size = (np.array(self.crop_size).astype('float')/scale).astype('int')
+ else:
+ crop_size=self.crop_size
+ bound_size = self.bound_size
+ target = np.copy(target)
+ bboxes = np.copy(bboxes)
+
+ start = []
+ for i in range(3):
+ if not isRand:
+ r = target[3] / 2
+ s = np.floor(target[i] - r)+ 1 - bound_size
+ e = np.ceil (target[i] + r)+ 1 + bound_size - crop_size[i]
+ else:
+ s = np.max([imgs.shape[i+1]-crop_size[i]/2,imgs.shape[i+1]/2+bound_size])
+ e = np.min([crop_size[i]/2, imgs.shape[i+1]/2-bound_size])
+ target = np.array([np.nan,np.nan,np.nan,np.nan])
+ if s>e:
+ start.append(np.random.randint(e,s))#!
+ else:
+ start.append(int(target[i])-crop_size[i]/2+np.random.randint(-bound_size/2,bound_size/2))
+
+
+ normstart = np.array(start).astype('float32')/np.array(imgs.shape[1:])-0.5
+ normsize = np.array(crop_size).astype('float32')/np.array(imgs.shape[1:])
+ xx,yy,zz = np.meshgrid(np.linspace(normstart[0],normstart[0]+normsize[0],self.crop_size[0]/self.stride),
+ np.linspace(normstart[1],normstart[1]+normsize[1],self.crop_size[1]/self.stride),
+ np.linspace(normstart[2],normstart[2]+normsize[2],self.crop_size[2]/self.stride),indexing ='ij')
+ coord = np.concatenate([xx[np.newaxis,...], yy[np.newaxis,...],zz[np.newaxis,:]],0).astype('float32')
+
+ pad = []
+ pad.append([0,0])
+ for i in range(3):
+ leftpad = max(0,-start[i])
+ rightpad = max(0,start[i]+crop_size[i]-imgs.shape[i+1])
+ pad.append([leftpad,rightpad])
+ crop = imgs[:,
+ max(start[0],0):min(start[0] + crop_size[0],imgs.shape[1]),
+ max(start[1],0):min(start[1] + crop_size[1],imgs.shape[2]),
+ max(start[2],0):min(start[2] + crop_size[2],imgs.shape[3])]
+ crop = np.pad(crop,pad,'constant',constant_values =self.pad_value)
+ for i in range(3):
+ target[i] = target[i] - start[i]
+ for i in range(len(bboxes)):
+ for j in range(3):
+ bboxes[i][j] = bboxes[i][j] - start[j]
+
+ if isScale:
+ with warnings.catch_warnings():
+ warnings.simplefilter("ignore")
+ crop = zoom(crop,[1,scale,scale,scale],order=1)
+ newpad = self.crop_size[0]-crop.shape[1:][0]
+ if newpad<0:
+ crop = crop[:,:-newpad,:-newpad,:-newpad]
+ elif newpad>0:
+ pad2 = [[0,0],[0,newpad],[0,newpad],[0,newpad]]
+ crop = np.pad(crop,pad2,'constant',constant_values =self.pad_value)
+ for i in range(4):
+ target[i] = target[i]*scale
+ for i in range(len(bboxes)):
+ for j in range(4):
+ bboxes[i][j] = bboxes[i][j]*scale
+ return crop, target, bboxes, coord
+
+class LabelMapping(object):
+ def __init__(self, config, phase):
+ self.stride = np.array(config['stride'])
+ self.num_neg = int(config['num_neg'])
+ self.th_neg = config['th_neg']
+ self.anchors = np.asarray(config['anchors'])
+ self.phase = phase
+ if phase == 'train':
+ self.th_pos = config['th_pos_train']
+ elif phase == 'val':
+ self.th_pos = config['th_pos_val']
+
+
+ def __call__(self, input_size, target, bboxes):
+ stride = self.stride
+ num_neg = self.num_neg
+ th_neg = self.th_neg
+ anchors = self.anchors
+ th_pos = self.th_pos
+ struct = generate_binary_structure(3,1)
+
+ output_size = []
+ for i in range(3):
+ assert(input_size[i] % stride == 0)
+ output_size.append(input_size[i] / stride)
+
+ label = np.zeros(output_size + [len(anchors), 5], np.float32)
+ offset = ((stride.astype('float')) - 1) / 2
+ oz = np.arange(offset, offset + stride * (output_size[0] - 1) + 1, stride)
+ oh = np.arange(offset, offset + stride * (output_size[1] - 1) + 1, stride)
+ ow = np.arange(offset, offset + stride * (output_size[2] - 1) + 1, stride)
+
+ for bbox in bboxes:
+ for i, anchor in enumerate(anchors):
+ iz, ih, iw = select_samples(bbox, anchor, th_neg, oz, oh, ow)
+ label[iz, ih, iw, i, 0] = 1
+ label[:,:,:, i, 0] = binary_dilation(label[:,:,:, i, 0].astype('bool'),structure=struct,iterations=1).astype('float32')
+
+
+ label = label-1
+
+ if self.phase == 'train' and self.num_neg > 0:
+ neg_z, neg_h, neg_w, neg_a = np.where(label[:, :, :, :, 0] == -1)
+ neg_idcs = random.sample(range(len(neg_z)), min(num_neg, len(neg_z)))
+ neg_z, neg_h, neg_w, neg_a = neg_z[neg_idcs], neg_h[neg_idcs], neg_w[neg_idcs], neg_a[neg_idcs]
+ label[:, :, :, :, 0] = 0
+ label[neg_z, neg_h, neg_w, neg_a, 0] = -1
+
+ if np.isnan(target[0]):
+ return label
+ iz, ih, iw, ia = [], [], [], []
+ for i, anchor in enumerate(anchors):
+ iiz, iih, iiw = select_samples(target, anchor, th_pos, oz, oh, ow)
+ iz.append(iiz)
+ ih.append(iih)
+ iw.append(iiw)
+ ia.append(i * np.ones((len(iiz),), np.int64))
+ iz = np.concatenate(iz, 0)
+ ih = np.concatenate(ih, 0)
+ iw = np.concatenate(iw, 0)
+ ia = np.concatenate(ia, 0)
+ flag = True
+ if len(iz) == 0:
+ pos = []
+ for i in range(3):
+ pos.append(max(0, int(np.round((target[i] - offset) / stride))))
+ idx = np.argmin(np.abs(np.log(target[3] / anchors)))
+ pos.append(idx)
+ flag = False
+ else:
+ idx = random.sample(range(len(iz)), 1)[0]
+ pos = [iz[idx], ih[idx], iw[idx], ia[idx]]
+ dz = (target[0] - oz[pos[0]]) / anchors[pos[3]]
+ dh = (target[1] - oh[pos[1]]) / anchors[pos[3]]
+ dw = (target[2] - ow[pos[2]]) / anchors[pos[3]]
+ dd = np.log(target[3] / anchors[pos[3]])
+ label[pos[0], pos[1], pos[2], pos[3], :] = [1, dz, dh, dw, dd]
+ return label
+
+def select_samples(bbox, anchor, th, oz, oh, ow):
+ z, h, w, d = bbox
+ max_overlap = min(d, anchor)
+ min_overlap = np.power(max(d, anchor), 3) * th / max_overlap / max_overlap
+ if min_overlap > max_overlap:
+ return np.zeros((0,), np.int64), np.zeros((0,), np.int64), np.zeros((0,), np.int64)
+ else:
+ s = z - 0.5 * np.abs(d - anchor) - (max_overlap - min_overlap)
+ e = z + 0.5 * np.abs(d - anchor) + (max_overlap - min_overlap)
+ mz = np.logical_and(oz >= s, oz <= e)
+ iz = np.where(mz)[0]
+
+ s = h - 0.5 * np.abs(d - anchor) - (max_overlap - min_overlap)
+ e = h + 0.5 * np.abs(d - anchor) + (max_overlap - min_overlap)
+ mh = np.logical_and(oh >= s, oh <= e)
+ ih = np.where(mh)[0]
+
+ s = w - 0.5 * np.abs(d - anchor) - (max_overlap - min_overlap)
+ e = w + 0.5 * np.abs(d - anchor) + (max_overlap - min_overlap)
+ mw = np.logical_and(ow >= s, ow <= e)
+ iw = np.where(mw)[0]
+
+ if len(iz) == 0 or len(ih) == 0 or len(iw) == 0:
+ return np.zeros((0,), np.int64), np.zeros((0,), np.int64), np.zeros((0,), np.int64)
+
+ lz, lh, lw = len(iz), len(ih), len(iw)
+ iz = iz.reshape((-1, 1, 1))
+ ih = ih.reshape((1, -1, 1))
+ iw = iw.reshape((1, 1, -1))
+ iz = np.tile(iz, (1, lh, lw)).reshape((-1))
+ ih = np.tile(ih, (lz, 1, lw)).reshape((-1))
+ iw = np.tile(iw, (lz, lh, 1)).reshape((-1))
+ centers = np.concatenate([
+ oz[iz].reshape((-1, 1)),
+ oh[ih].reshape((-1, 1)),
+ ow[iw].reshape((-1, 1))], axis = 1)
+
+ r0 = anchor / 2
+ s0 = centers - r0
+ e0 = centers + r0
+
+ r1 = d / 2
+ s1 = bbox[:3] - r1
+ s1 = s1.reshape((1, -1))
+ e1 = bbox[:3] + r1
+ e1 = e1.reshape((1, -1))
+
+ overlap = np.maximum(0, np.minimum(e0, e1) - np.maximum(s0, s1))
+
+ intersection = overlap[:, 0] * overlap[:, 1] * overlap[:, 2]
+ union = anchor * anchor * anchor + d * d * d - intersection
+
+ iou = intersection / union
+
+ mask = iou >= th
+ #if th > 0.4:
+ # if np.sum(mask) == 0:
+ # print(['iou not large', iou.max()])
+ # else:
+ # print(['iou large', iou[mask]])
+ iz = iz[mask]
+ ih = ih[mask]
+ iw = iw[mask]
+ return iz, ih, iw
+
+def collate(batch):
+ if torch.is_tensor(batch[0]):
+ return [b.unsqueeze(0) for b in batch]
+ elif isinstance(batch[0], np.ndarray):
+ return batch
+ elif isinstance(batch[0], int):
+ return torch.LongTensor(batch)
+ elif isinstance(batch[0], collections.Iterable):
+ transposed = zip(*batch)
+ return [collate(samples) for samples in transposed]
+
diff --git a/training/classifier/full.npy b/training/classifier/full.npy
new file mode 100644
index 0000000..1345bfd
Binary files /dev/null and b/training/classifier/full.npy differ
diff --git a/training/classifier/full_label.csv b/training/classifier/full_label.csv
new file mode 100644
index 0000000..55294f9
--- /dev/null
+++ b/training/classifier/full_label.csv
@@ -0,0 +1,1596 @@
+id,cancer
+0015ceb851d7251b8f399e39779d1e7d,1
+0030a160d58723ff36d73f41b170ec21,0
+003f41c78e6acfa92430a057ac0b306e,0
+006b96310a37b36cccb2ab48d10b49a3,1
+008464bb8521d09a42985dd8add3d0d2,1
+0092c13f9e00a3717fdc940641f00015,0
+00986bebc45e12038ef0ce3e9962b51a,0
+00cba091fa4ad62cc3200a657aeb957e,0
+00edff4f51a893d80dae2d42a7f45ad1,1
+0121c2845f2b7df060945b072b2515d7,0
+013395589c01aa01f8df81d80fb0e2b8,0
+01de8323fa065a8963533c4a86f2f6c1,0
+01e349d34c06410e1da273add27be25c,0
+01f1140c8e951e2a921b61c9a7e782c2,0
+024efb7a1e67dc820eb61cbdaa090166,0
+0257df465d9e4150adef13303433ff1e,1
+0268f3a7a17412178cfb039e71799a80,0
+026be5d5e652b6a7488669d884ebe297,0
+02801e3bbcc6966cb115a962012c35df,1
+028996723faa7840bb57f57e28275e4c,1
+0334c8242ce7ee1a6c1263096e4cc535,0
+03fb0d0fdb187ee1160f09386b28c3f2,0
+03ff23e445787886f8b0cb192b3c154d,0
+043ed6cb6054cc13804a3dca342fa4d0,0
+0482c444ac838adc5aa00d1064c976c1,0
+04a3187ec2ed4198a25033071897bffc,0
+04a52f49cdbfb8b99789b9e93f1ad319,0
+04a8c47583142181728056310759dea1,1
+04cfc5efa4c8c2a8944c8b9fa6cb04d1,0
+04e5d435fa01b0958e3274be73312cac,0
+04fca9fbec0b803326488ade96897f6e,0
+05609fdb8fa0895ac8a9be373144dac7,1
+059d8c14b2256a2ba4e38ac511700203,1
+05a20caf6ab6df4643644c953f06a5eb,0
+064366faa1a83fdcb18b2538f1717290,1
+0679e5fd67b7441b8094494033f3881f,0
+0700108170c91ea2219006e9484999ef,0
+0708c00f6117ed977bbe1b462b56848c,1
+07349deeea878c723317a1ce42cc7e58,1
+07abb7bec548d1c0ccef088ce934e517,0
+07bca4290a2530091ce1d5f200d9d526,1
+07fdb853ff90ce3c6d5c91f619ed714e,0
+080e6a00e69888fd620894f9fd0714b1,0
+081f4a90f24ac33c14b61b97969b7f81,1
+08528b8817429d12b7ce2bf444d264f9,0
+0852f5124d69d7f8cd35fa31e1364d29,0
+08643d7b9ce18405fb63f63dda258e76,0
+086f95a932c83faed289854083f48831,0
+0890a698c0a6ce5db48b1467011bf8d2,0
+089b8f10743e449a0f64f8f311dd8a46,0
+08acb3440eb23385724d006403feb585,0
+099cec971282b1531d297e5d0d423598,0
+09b1c678fc1009d84a038cd879be4198,0
+09d7c4a3e1076dcfcae2b0a563a28364,1
+09ee522a3b7dbea48aa6d39afe240129,0
+09fdf599084b816247ba38d95b3c9d80,0
+0a099f2549429d29b32f349e95fb2244,0
+0a0c32c9e08cc2ea76a71649de56be6d,0
+0a38e7597ca26f9374f8ea2770ba870d,0
+0acbebb8d463b4b9ca88cf38431aac69,1
+0bd0e3056cbf23a1cb7f0f0b18446068,0
+0c0de3749d4fe175b7a5098b060982a1,1
+0c37613214faddf8701ca41e6d43f56e,1
+0c59313f52304e25d5a7dcf9877633b1,0
+0c60f4b87afcb3e2dfa65abbbf3ef2f9,1
+0c98fcb55e3f36d0c2b6507f62f4c5f1,0
+0c9d8314f9c69840e25febabb1229fa4,0
+0ca943d821204ceb089510f836a367fd,0
+0d06d764d3c07572074d468b4cff954f,1
+0d19f1c627df49eb223771c28548350e,0
+0d2fcf787026fece4e57be167d079383,0
+0d941a3ad6c889ac451caf89c46cb92a,0
+0ddeb08e9c97227853422bd71a2a695e,0
+0de72529c30fe642bc60dcb75c87f6bd,0
+0e7ffa620c6db473b70c8454f215306b,0
+0eafe9b9182b80c6d67015a2062f5143,0
+0eb39d23d0f68ade9b5d8e6b3aee04d2,0
+0ee336c585bf7eb1011df476891c5102,0
+0f5ab1976a1b1ef1c2eb1d340b0ce9c4,1
+0fb1b54da1e66c60a57db9c52f945e25,0
+0fe244f21893c45fbb877f54d008518b,0
+0fe9dd36f4dece7f4ec017433c4d4a50,0
+0ff552aa083ecfabaf1cfd65b0a8e674,1
+101a2999d28ce05788e6add3a28d4726,0
+1030bb45e9f660c3466f013dcb270520,0
+1098cb63ea33f752a850929234576bcb,0
+10a9c32039971eb12f3aecf76ac20f8c,0
+10aa518193fa5b89b305a806d1dfb150,0
+10f03fe0b77d39c758d6fb12304edfdb,0
+10ff16e329c64a6a290a7a4139a5f4ae,0
+11616de262f844e6542d3c65d9238b6e,0
+1183f213c1c821df18aad63890920403,0
+118be21b7e0c3058b29a524686391c66,1
+11b09ff9de7382d83f79cc81f89f5894,0
+11f10c2a0bfd231deeec98d69e4d0767,0
+11fe5426ef497bc490b9f1465f1fb25e,1
+122c5c959fd98036c9972eec2062dc59,0
+124c4188604434bcdec8358c8ddf9a8b,0
+124e68a78f9c092a2f16f9214e91268f,0
+1278988821a696e534c6c93ecdd4ff0c,0
+12e0e2036f61c8a52ee4471bf813c36a,1
+1344e604281e68ac71f25c02e7637992,0
+135f21a84ac903a1d8dfbb0dfe46d792,0
+13bb12b3b27d5a7b4b142503a1ae9e73,1
+14248ec22193bed1e087755df5a28509,0
+1427be78bcf4aba96c5054b697be9b5b,1
+149cc798827099f8bdb97cf702027305,1
+149ff4b37a684a73869d2d88e3fd4d0e,0
+14afefc82d992018c485949285d20c03,0
+14c534e0b7c3176d9106c6215d0aa8c6,0
+14f713c1ef037f6c531cffdff0e5fb2c,1
+154a79706bcecd0402b913d4bee9eed7,0
+155893351afed6c68893397d19555fd8,0
+15aa585fb2d3018b295df8619f2d1cf7,1
+1615ace332b9d79be4e0e9fa32c71e9e,0
+1631637f08f27347e8f23d7a0e18c100,0
+16377fe7caf072d882f234dbbff9ef6c,0
+166a2a476b7b84c975fb65162acc0798,0
+169b5bde441e8aa3df2766e2e02cda08,1
+16a4184e565f589622a70e82957ab54e,0
+1748ad43b222be66f3e5ae4bd70c02ac,0
+174a9fc87f54d6def3730954fbafc99d,0
+178663e1e238cdfa4d4eb9679e5d0aa4,0
+17f5ae9fa49c4e47624f344d29bd03eb,0
+17ffaa3e8b53cc48e97fc6b87114e6dd,0
+180737a8b34cf2c88b00dfad3e7556ae,0
+184c61740244f4ce8fb985af9bb3d8e8,1
+184fa4ae2b7ae010625d89f10186f1c5,1
+185bc9d9fa3a58fea90778215c69d35b,1
+186a0877503b047a77eb9b38083be9c1,0
+186d95f7c17fd666726c10251072d44b,0
+18f49fee33af677f0ce2ba655c5ec835,0
+191fa0e017185de2c802bbe94edad2ed,0
+19409b302d6c143d4f754146e91d4cfe,0
+195842462645f0f331147a4c6b129a37,0
+197e035d3aed52b5a2a0de3ee4d5fcea,0
+198d3ff4979a9a89f78ac4b4a0fe0638,1
+199ff05d08ade6e298d37cc542bc3565,0
+19bb6a9bc007ad75a4777e5298354cb4,0
+19ca60da880961c50f1b99b66f252e8f,0
+19d95b5828aeba8073fcbb12979f312b,0
+19f3b4dea7af5d6e13acb472d6af23d8,0
+1a41350d4bbd74b7e0e28239cefa84c2,0
+1a91ca95390756518700877893ac195b,0
+1a9e2aad4b87512636f4f9d82c36a3ef,0
+1acbe17dc8f9f59d2fd167b2aa6c650f,0
+1b17c83c3b0cb973e41f9121e562d030,0
+1b2355e6054759f2f0eb2542ed382b78,0
+1b7ca8dad5c36feb0a6abf8079173e22,0
+1bb17a55702a78142cd05cd1063c82c8,0
+1be4cf2de84adac4de0e090c9a15461c,0
+1c05dea5723caf192af34ceb5804468f,0
+1c24a09fa32147d9083ff93f171e1102,0
+1c42a5da837f4122d2c3b59ca9b5f0fb,0
+1c498f306808952739e7a3a3a2439d1e,0
+1c81d86923dad37b411f3a5936eb622d,0
+1dab3271160e1380c5a70a1e3ba40cb7,1
+1ddb5d17d9db61c8ea0fd58d00df05ef,0
+1e0f8048728717064645cb758eb89279,1
+1e33cb12436a64853c1ae9e918633e05,0
+1ec082e8e2fa6eb6366b72a13e47b50f,0
+1edf5480bf676f8342a7d516bab58fa0,0
+1f49f0c1d7feedcae9024d251797407c,1
+1fb4887efd403cd9c0f6970fc8b679b5,1
+1ff6e2a80eb74396e09460c61ae69fb0,0
+204bdd4a15f023eea66190972b66fd0f,0
+20809d879e5a966cc537beb42735a67f,0
+20c73e37fc89e007ae5b242480830860,0
+2117642550461db380a019bbd10a95e5,0
+2143d78ca33eb69f667edd80ddbff6de,0
+21bdacdcdb87bf401f34d5d582247c77,0
+21c94e2776145f74697adf8810b05305,0
+21cfe28c4a891795399bb77d63e939d7,0
+21d449f3ae00ea302e5aa15d7df65465,0
+220223b46a23db0e2b0577170936845d,0
+2276fd918ac100cec3ed8036f6ad401c,0
+229b8b785f880f61d8dad636c3dc2687,1
+2346e52f9370d9dd58172eb44b2b5d87,0
+234ac5dd589d09a4b2a753ff206d5588,0
+2365e0afe6844e955f3d4c23a16dc1a9,1
+23e309ef3a674bcd9c8df40614b93a8e,0
+24031ba88c58797148475f6d4d5a085b,0
+243e69389ae5738d3f89386b0efddbcd,1
+245fe0c86269602b0dab44c345b0b412,1
+24626abe1c4544fb39d4e96e33275789,0
+2488c5b32e837dc848fe6fe4b1bbb7cb,1
+24deb9f7adc838e4a4aaa2c905c548e6,0
+2505ca2e3cd132f69fde96ba4bb50f7b,0
+25196c504274d166e81c745d32f30c72,0
+252b5fd5c4a5eb77be4fbe41df49bd07,0
+25782c40c29f7d774f8b644f3e68b590,0
+25a3b616f6cc89e74f6502d65b687972,0
+25c1c4f008e8addc4d386cab58815052,0
+25c369973827571098bdebf2a15c6ef2,0
+2615d445b6d3865407d1a4422d25058e,0
+2619ed1e4eca954af4dcbc4436ef8467,1
+263fa87394ee296e31234364e75d05e2,0
+264e5829ef58570c243bfd961098343f,0
+26a2b8d6b94ee16ecf88fb28c57f377e,0
+274297dd9a4f66148754944ae2b6731c,0
+274a81c75d244187247789bd71de2b3a,1
+27e9f8b51aeee67918221f2df98e9cbc,0
+28054f63c5a6ef24e06d8c34258babd6,0
+281bb28a077ccfcd40ce4a543a5aea89,1
+28352e12fe29361dfd9613ed2e729192,0
+28621a6988deb389673605447f46d3bb,0
+28649e08938386e3b8eaa4a84baf5982,0
+28824d52b6425841bb263393c3211693,0
+2885e3af725bc58dc1522d4bfb24bb2b,0
+2895ce2fe73dd62554326c3ab1c3b686,0
+28a9b77a9113ce491433d3ea47fa8fc9,1
+28e29fe26140703e5bbe570f982bd112,1
+2922aac33a190fd3939de337fe3f0a34,0
+2950df9632577cb4b3af2dbfe2086b11,0
+2969c7ad0e550fee1f4a68fcb3bbb9e5,1
+29883252ce0ce3e052ce8cf4932623af,0
+29a2105c99e7677c30c7fd0b2edb9fcd,0
+29d92a1e253cef2c7f34c6db26ce11e3,1
+2a20e4a4e6411f72374fdffebabfc235,1
+2a2300103f80aadbfac57516d9a95365,1
+2a48f50391e22040f28e258a74dcaf95,0
+2a549c66f24af964de6f25165c55e331,0
+2a6433cf347f7bd52ab796f083003832,0
+2a65c8b6d5cc50866de8caa4caabbb6d,0
+2b0ea2696c8a02af5ac22f142be28e17,0
+2b2a95f76d7b6712690ee7be6838f868,0
+2b55d9c3f8e05951c87e90d2361aca6a,0
+2b861ff187c8ff2977d988f3d8b08d87,1
+2b89691a0744504491ef91d711d94918,0
+2bb5f7e8f10e1e39b7f81b5aa98676ea,0
+2bf773632e786951d6d594939e6f4713,0
+2c06f5c66f3c79515b7712605dea4400,1
+2c51b9e7af4850d817f4aa0ddf90b852,0
+2c8e0b1e8a3f10b1d59e4aa8fe68a32e,0
+2ce2565b9839d8812cf0f9ad80371d3f,0
+2d5cd7c1ee9a74a1244ddd6b55ad0446,1
+2d8152c603e6c49593578bde8e388860,0
+2d81a9e760a07b25903a8c4aeb444eca,0
+2d977650e6388d2c45825a77e94437a2,1
+2dabff545dbfcb9e0efd92220c6aebcc,0
+2dbb8c6c6ea4ff5c62b34bdf9ea03158,0
+2e26f46f1edc232be164c1fe2712e96a,0
+2e59e2064d391f4b2587a08aff671399,0
+2e8bb42ed99b2bd1d9cd3ffaf5129e4c,1
+2ea91bfe303ec03f9b0b3603333a3de6,0
+2eb8aedb5274414e05041b7be65db3e3,0
+2ebb1e8f14802c33f0e4215a7545d70d,1
+2ed2ec628e6ad9d0aa8c2a9b7bf4c4ce,0
+2ed8eb4430bf40f5405495a5ec22a76d,1
+2f154a687b94f7b59fec7048cbfb5354,1
+2f4645c27f9806daffe7e9d013b4b7eb,0
+2f4e4a808cfb348d6ddc81de96f72077,0
+2f7088e4008c0ef2c88b6764af8c8815,0
+2fa939efbc3e1c2bc57ba5a98922ff3b,0
+2fc3d8ef26fc7aafad44d5034673dd4c,1
+2fced53a125854edb9284ff12795caf8,0
+2fd66be0a5e07b8bd4be1d8169cd846f,0
+302336ac736ed66077456775a0a99adc,0
+303b4b8425389134997a38b975c205d3,1
+3043b5cc9733054f3ab5399c3c810406,0
+30b8aa7f5688cab5ff0964f34b715c4d,1
+310b403db75226a9a44d9a29c18917b7,0
+31136e50b7205e9184227f94cdea0090,1
+313efe2e7ecf18a8d484f8b42f30da3e,0
+3170d41d2bc132db30399fca6bc6f376,0
+3187b6cf14ed2cbe611b01da5e161f21,0
+318bf8045b625b40825552420abfe1ef,1
+31c090cf66ec7bf090801d14d63199b5,0
+31d037f6e359b56aec064fd3e348adb5,0
+31e82ed2c875eae8dfbfd70ac440458a,0
+31f35f920a472a1c3eacb565fe027923,1
+321364cc2393dccb7ba8894ee9d2b269,0
+322bf0acacba9650fa5656b9613c75c8,1
+322d09835e9c6f621262ee68fd3ed596,0
+323792e42c4f43448b2b1a9651ecb779,0
+3244f802b7bd7c02ba7a8473802e947d,0
+3252220375d82c3720d36d757bb17345,1
+327c4e9f365aec05222e253d1a80a1d4,0
+328138837e6db638913332acb79c703e,0
+3285ba0f447f3091c0c7c061b47c2f62,1
+3295f3f392d8e130155c8912b60161b5,0
+32cda856b7ec759fd3ebaa363c505e88,1
+331b14e413e88542855664c845c08c63,0
+33293edbc834da033aa061f7d6a45fa1,0
+335b129aacabdf9269b0bb12f148d15c,0
+337e7a428e7342d1e7f53a04247f7ad8,0
+338f9c6da34f61091a4c44b074b2f9e3,0
+33da5fb759223c316e8cec9d884d1584,0
+33dd6666d9f0338929ecce58bb7c4cc3,1
+33e0e8629a377e4554b26e60a1007788,0
+34007dd2549af2b82cc1206e550b5100,0
+344ab37041900393b5498bdda6f43cac,0
+3457880b1a66030feb8adaed6da805af,1
+3464083b3e6e7c11d1fba925f0b914cd,0
+348a53f500ada390ddd00cc47d310b2c,1
+34b00e3b98072207edd20732558f7ab5,0
+34c0760406297a3c8fd5077fb7cd95b0,1
+34cb3ac3d04e0d961e7578713bee6bb2,0
+35105d801880bd889bac5ee3771ed38b,0
+352c23fe8a3d0640ea531a6bf223732c,1
+3557455d81f42ee54ad0544f36933e9a,0
+356bc45910503ffde017a066581a3798,0
+359951e3d2768249211361665b99b735,0
+35ab1899e939be4e67923a1624c91365,0
+35b9a3e9871499893f76c8e6c648562c,1
+366cfab448dbe55fd63b01adac0b1c56,0
+36d0dff4c9eb340475888c2f93359e43,0
+36dcb6b7463ada9ed78ce902d6f8ddc2,0
+36f4fca6bbd993088ee024f93a61b722,0
+37006435aca7184571bba3c907141e82,0
+37030ab5889febdae6725740aa627f95,0
+375a52b012066845a2eeb5032a92fc6b,1
+379d84cd171e6c0e58455c2fd0cf57ef,0
+37dbe298bb4e0199625689cc35d390bb,0
+380eb569a5750648434cc8ae8da4a0a9,1
+383c27906392e9ce57f6ab5ef1cb6f62,1
+385f1f49b0c20563177c36b7470f1c46,1
+38d89e67d2ea7e2ab023c10f5f19f716,0
+3938d2274f0576b70fffa9aa68af8874,0
+398208da1bcb6a88e11a7314065f13ff,1
+399a263bdfbf26c6969d8af98774be8c,0
+39c3a2d2ca67bc7a1a22240ea571d50c,0
+39c404ac6b5852fc8ff00d34bd35294f,0
+39dc5f09d7b8eeda7f2f02c86f53247d,0
+39ebb8121ea6faec0405a4e8db883b55,1
+3a1a293ecad44010da9907bfc91d94cd,0
+3a3a7a6b3d2a4ea6b1f5bc6ea715eab8,0
+3a5bbc2f1f5d6d76a48ba5300105d998,1
+3a78dcf53effd732bc3880c029154272,0
+3aedb9550977ed35e7d44555207ef739,0
+3b59edf7e74fcff927c912efc0e80f3a,0
+3b7384f374b73d2bd589ccbf1b651820,0
+3b78adbbe463aba48bf29613ca37b2ea,0
+3b908e86ea0f7cbd05dd8e0ea6d45d79,0
+3bbab45d770ecd681be143f67cb4e5f3,0
+3bd4f83c5930e8c1e193ccc463543745,0
+3c2dbbdeb857504a8b501fc013b99c90,0
+3c5a0fc6890a1f84211cf8a75c1b83c4,0
+3c73f5597780b7312b380373fb897f40,0
+3c86ed658e82e542bc542886a59ea4f1,0
+3cdd66bf14f0cff5cb46e95d5867de0d,0
+3d2b2b0fa9697b298fbbc033481cdcc4,0
+3d4e602819dca0f5eb48953841ff11d6,0
+3d521ee3776eefb65953f89c0e1a4f96,0
+3d5351d09a432a8de88e5b270d419ebf,0
+3dfe8e80106f4136d2933ff72a16035c,0
+3f057e68a02e9951b268227649f4a7d6,0
+3f28787cc3343445a8c5ecc4dae27a25,0
+3f37745d6516c29c597b797c50fe7839,0
+3f6431400c2a07a46386dba3929da45d,1
+3fcfd27d83883f454ba2fe58dee4abea,0
+4001d754871a8da824b8444e32dc6e0f,1
+402a18fa05523f80abb1e6d97793cc19,0
+404e5dd2b032a223282f5a5e73c05418,0
+4062f1ad138218af5a3dfa3186d2afe1,0
+408646e125230c495be91fe171da736e,0
+40c044145f5c87c12bd8c725924add3c,0
+40c95c9be0bd7c290534ce374c58bec9,1
+4131820511c86a5e6b1e7721ab687049,0
+415ea74bca59eb0ecd5ebb9c2c545f9d,0
+4165b6e956c0e46e94abf7d98f8d8fe2,0
+4209cb1fbce28cd68da900eb9bef26b3,0
+428e25dfddfe731fc73f4e1739422181,0
+42bfcfb0e3965039947bd905b2fc3915,0
+42dbd247a9e5f710926b7c049a00ff48,0
+42e374c728e50cf2aaa78db97f24a82c,0
+430596d1bfa6ec9a7bfa7359194a561c,0
+432f8765e6b590ec00cc34c8d88456da,0
+4348beb99dacd2cbf14983a2c64a00c6,0
+435cd5883a2014f295a8081ea098674b,0
+436fd6ccfc92afc44c7d3ccfe26b6129,0
+437e42695e7ad0a1cb834e1b3e780516,1
+43933b4021d93dd64854f318656c7d1e,0
+43f2ef8f53e1aa03bfb6378d0c20a8ac,1
+43fecc8947e4fbb47968dc8ef7d8f4ec,0
+43fefd3f810ef71e0073d2415e7a6713,0
+44012bec8f33a785f7844cea8910487d,0
+440fb90654b1436e7c3bbdac991b8c1d,0
+4419818b57ef8b0f8d6d95594adab922,0
+448ce51772879fcd88f61c07b06347b2,0
+44988c6efa451e8d496188cb30669d44,1
+44cd94d1228f4a70753b5dfc12703414,0
+4521c94debf37a4dc9f3b70366a21640,1
+456a7dd28233b398ac83f03c80447b5a,0
+45a8417be8f56b401bd7b5d106f5acdd,0
+45efbc7cc2657278f878bc973cecc141,0
+45f4141cfe3f110f9db4e1e113d15684,0
+46199ffd681fd429aca3823c76f1034d,0
+463b67fefdde16ba3c4a4258de1f38e3,0
+479078cdf18cd6b677b79d2d9b075d81,0
+483b89a4ffbbd85acc8b9af5a541dd4d,0
+4842c8c0a3f387effde44cb9b3d3fd2e,0
+48713d11ced3c60a531e6e80258d6425,0
+487cc9003c99fa95e9a9e201d396992c,0
+48e592418247393234dd658f9112c543,1
+48fac79fead32f2b10e37752cb077af6,0
+493641ef65ee95fe994d4789aec1db3b,0
+494b9a6714921a446b32959ca291b050,0
+494c42cb61c1e4a02504c16fe09a8129,0
+49a29b3f5bee32b350bedc4cfbad8e9c,0
+49b5b3444cf977439600dd06e8dd84ad,0
+49ee28b71e02be4689e3fb0ba2a32c2b,0
+4a1391269629d20359325873d11413c9,0
+4a782bbc2608288a3ed05e511af6f8bb,1
+4aa3131e76b28e30235664087407edc3,0
+4aea6c3360cd923d25f33ec5b5e643bc,0
+4af17bcb31669a9eab0b6ef8e22a8dcf,1
+4b19444c570185fc4606e4e29fd1ce1c,0
+4b2f615f5498ee9d935b0229a2e6bb19,0
+4b351d0c19be183cc880f5af3fe5abee,0
+4b5970e5edc0d8389cabc6bc5d84265f,0
+4b6b53281fe1fe797e181a5287df0f9a,0
+4b7f72b889e85b479305f8fbc8cc4f48,0
+4b8e47f2a5edda13b971da27317bfc6f,0
+4b96e8e085d7ab16c8054654fe586553,0
+4baa552f3a11782f39e16b345d401fb8,1
+4bf6fb574a2ca2da551609e98a573e54,0
+4cc309d81bf3685d7def772862375a2a,0
+4cc8af2efef2f41bf70684be25276ce5,1
+4cd70a98baca46b116071b32788d3c2d,1
+4d207541fac845d1a369a160f15d55e6,0
+4d621b0adb6b46b353056e1843621c5f,0
+4d7df08f074b221eec6311c2617a5ba8,1
+4d86e1657d46b9ee44c2c434fad231ce,0
+4d8f4de444a1f453e7ad32d067b0f630,0
+4dade0813da186d968b4b8c4952cbb0c,0
+4dbda61d574417c7f25d6e9a8f0749a7,1
+4dcd34bd9b10f96453b63d4f55d1fd44,1
+4e9c2cbf385db44b6f5e6618f47318d9,0
+4ecf053654c565e4a5d0f37811eade66,0
+4efa432089851f50a5f53fc5a12e806a,0
+4f1573f5cab1aaaebff33287682c5fbd,0
+4f3039ae82f8cc764d1ec21116f54a07,0
+4fb3d996e87999e0dfa0009a3e5f0fbc,0
+4fcf8b00ea7a99162dc70aba253ba669,0
+502d4601458807bf0089e6fd07825357,0
+502e157e6a22166997d054e8920d921c,0
+504e447ad62ea9ebb283873e044b5dd2,1
+506b07466777f6c6f4dd50a42896a2c4,0
+512397206b42f1f8d009113511ae2937,0
+51bd5c556c77ecdaf489d8dd9f7a05f1,1
+51fbac477a3639f983904fc4d42b8c15,1
+521924ac2f00a62cc63f679de7e599cd,0
+5253d873ff82e3fa69e30e542d13a4ce,0
+5267ea7baf6332f29163064aecf6e443,1
+5275c7ec0f1d80c829611c378708c05b,0
+5278093ed7187e1a8be518d954509da7,0
+529e4dd38822b413a4a87e6f4faa5f23,0
+53087ef723e2433ad0b8041e408c6f8c,0
+5368521797323c89292781b8780e45b5,0
+538600927ec2970552917a29b490b5fd,0
+53ddfb7769619035ad7f8f58c72f697c,0
+54056288ab97cebc4b0ea33c23f47ff6,1
+540dbb66efa0f76499464689756e69f4,0
+54162a514a5e2beb54e4b7aff41f5dfe,0
+54d421d543e9e6dc8db10066a5867081,0
+54df448f6c74df6bfa6b75c05393ace1,0
+5518b27f000e34cf2db5a362f4fac613,0
+552ef3f04be2073d2cf8a52431576c24,0
+5572cc61f851b0d10d6fec913ae722b9,1
+55baceb599dc8aefe4b13c131d0531df,0
+55c01868f1d9c37fa3f174dc3c0d44e8,1
+55d88980822c2e5d39b3d0ec172fa101,0
+55e476ee19742fc09c4ce5e6ebdc13d1,0
+55eace190c5917cdfb390ca652149fbc,0
+56462ba8833fc842d16be7e311214404,1
+565cdee745ea4e6afc0f7daae81a7963,0
+566a5d958f17d2fc44d4a1ec00401034,0
+56995718fdd0a0549d0e7f11eb307f34,0
+56d38d6863fd160da38b15bf12f0ed64,0
+56e0f421b7faddcae027d7feb6dae8cd,0
+570ea80b0dcc08f3e8751a6f4b2b1cd5,1
+573a661e2d784f9385a3b78c9757ddad,1
+573e900142c9e6e7b32ed9e5ffd5584c,0
+5765dc0dbc8c02a4c862563eac4950ef,0
+57822feb6186b788c4e1877123428454,1
+5782e6873c666529c6a66421acb043dc,1
+579dfed23d49414a2c080bbf9d7f958f,0
+57af0020213d64598ede82fe9d6bb8b3,0
+57f5dc474b6a35d02542299dd09e68d6,0
+5818c3be99a83ca8c951ff3434750d6a,0
+5861f8f8e35c0713c61e8ab3bc54c905,0
+587d6230f2bad2525c47632fd792a895,0
+58bac12ccb44919bbd64271f38ee0584,0
+58bf189f6021ecea213c13eed7484d84,0
+58e4646cbead2fc4a6a1f86bf806e76f,0
+591f6b47c1362410e7f4c13afbc99d79,0
+592c2481f17d6a2cecfe7bbb6a27722c,1
+5968ac45330d7f24b041a73925818269,0
+597643aa6bb96b705eac52e03a307d6d,0
+59e4985cd165f3abbe888475ce564f3a,0
+59e4e8889ae68a75227b2bd02c1d1b96,0
+59fc9d939f05bf3023c1387c1c086520,1
+5a06cb92ba004e2265ab087b5b09e33a,0
+5a2e359e859d0b0d7c159fff87950852,0
+5a57009fcdea02d30d31a47d2454dc29,0
+5ab68460985d9ed8e952475b402ddd62,0
+5ade88428e6463fa212d4c287228e8ed,1
+5ae03fb6d9959aa93d1177cfd70cf760,0
+5ae60d42ec7eb7a79ce9a72967cbb6aa,0
+5b412509bc40a3aeb3b5efef1fdfcfc9,1
+5b4f56936ab57ee5b30d8752652ee5cb,0
+5b642ed9150bac6cbd58a46ed8349afc,1
+5bb9185543527cd034aa48fc0b623874,0
+5bf71718aa1bdcada76f0683f8d6b41b,0
+5c0d992d01e6383d5684b8ac5d7143b1,0
+5c4c25f93529bf21469f81a0acd5d324,0
+5c69c62e94dde61c690563eb3553a561,0
+5c99ab7172afa78312fe73a3c0dd342f,1
+5d240c6a6d3009e61cb09ce49f641b4c,0
+5d801b07718dc9a1ad2bf701523a0f74,0
+5da3dd09c0d0d597287a9a1046cced37,0
+5e0c8cba8eab51076ac0014049d770c1,1
+5e21909f11ec07f75460fe16b6c0185a,0
+5e371e8fda27df3e5cc2548868229d5b,0
+5f19d1c7bd7ceb691639cab9c1c2cb19,0
+5f383eb9c3d8ea72ddec7e2e874d577d,0
+5f3b9b59f957fea0a5e8cc506e12652e,0
+5f4e23c0f76cd00aaaa6e03744bbc362,0
+5faa4b8d9e86c157b7b16e67f22e7210,0
+5fd33ea74e1ad740a201ae9b3c383fc5,1
+5fe048f36bd2da6bdb63d8ff3c4022cd,0
+60018d051926d01b38dd16e44159610c,0
+605d3633c1625b4be151d38aad43de94,0
+60638c0dcee9e5adfcac3b4f57d1366f,0
+608202eb3c368512e55e9e339a203790,1
+608a7028689c6ab3aea5f116007169b2,1
+60a4915d8662dff30dc596ebccb83b3c,0
+60b1526597b82c98ce96fbe5014c0f2b,0
+60b389fb2f7eeb912586d1a3ccc9dbbc,1
+61406252b7c29fbe372adfa953d95199,0
+61630ec628631f7fe3980f869e1a4fbe,1
+6171d57221e26d1f15d3c71fe966ab18,1
+61917cf6407e793bc0edb60850009e85,0
+61c0247462b00b95c4df16edd4486a06,0
+61ce76681b4a68b8d0f3b724c1e844b3,0
+62099cb774faa70d28d2c5cb1e235270,0
+624a34fa8fd36847724e749877343847,1
+627499714e279203bd1294290f8fc542,1
+627836151c555187503dfe472fb15001,1
+63b5be42543c98ac5392f1bfbda085bf,1
+63d907adcf3f12349a0c2c8921d38e89,0
+642c43727eee4bda71c0c30bf5cf1a2b,0
+645e7f46eb9b834153ecf8e2b2921fe5,0
+648c99653d512edc1d28dd8e7054ceab,1
+64a5a866461a3b6006efb0075e04dffe,1
+65073aadb60e398d8db1806f5ea2a082,1
+6540e089936a6c9d1f11939e96e6ab18,0
+6541df84fd779ba6513a530c128f4e9b,1
+654f2095bace27af870cdfcc66f9717c,0
+657dc5d2bf8ea210d912dd8320481068,0
+65a380c07d416f78e85545eaaa2916a1,1
+65dd5d9d5b894e5f0ac3bd6c1384c46a,0
+65f596f75eebf7935554eaed3c8172ce,0
+661ffa992ed2c23c37f1e7b82dc834d7,0
+662153a685fb4268361bfbaca5e9ca23,1
+6629e23c3bdc8dc8161b3caa8a6048c1,0
+665ca5ce18dd06722a4c4436a85246b2,0
+666becc9794c25bb8e0e7982be7cb6dc,0
+666fad0dca00694381eeec67adc909ec,0
+6675d3cc20585f44d4c45746cb1002d4,0
+668bb968918c63fad7d65581825b1048,1
+66a92d789e440d3dbef3c69d20e20694,1
+66a94647459dd5a13f4336e1421119c5,0
+66b7666912e1d469cd9817a1cade694c,0
+66cef72d8428dbba31f2ab01abdaf6ca,0
+66fb40934f0be4b301fe27db7fb62299,0
+673ee14e01a0628b45c78500d402056e,0
+676467220abd8e2104417c5213664ef9,1
+678c5ec1360784e0fe797208069e0bbb,1
+6799964c08ad5ce7740defcd3bd037a6,1
+67ccc2ecd7716e1cab05caaedea99f4b,0
+67e87fa621f2e3e838b1b17a898d5b41,0
+67f7f74220c08faa756b34cb81b203a5,0
+6828335aec9aa0d0053ec0949319aa4b,0
+6857c76be618bb0ddced5f4fecc1695f,1
+68a1f729eb1e2a791fe8170ac6631828,0
+68e905099a1c18242aba55c9901eaaae,0
+68f2b9c1fae9180356cb5c4fa95bd30a,0
+6969c031ee0c34053faff3aac9dd2da7,1
+6997b392b28529c9ab67add45055fcf7,0
+699e4f02a11a33930a14b13071d24eb0,0
+6a08bc7a3156caf9b07bbb1f9b2861d2,0
+6a145c28d3b722643f547dfcbdf379ae,0
+6a7f1fd0196a97568f2991c885ac1c0b,0
+6ae190bcd3fd9c581db4120f4465d65a,0
+6ae1b284936accdc4101c6daaaa2e0d3,0
+6af9fecd6807921fa9fe10f0391aa453,0
+6b4837a316e688d0ba125cc1e545d383,0
+6be677ba1631174397b0c1e26a46af30,1
+6bebfec174e8a6e8d4b1653c13fcdbe5,0
+6c1136ce7fbc5c7b503aa08da6abedd2,0
+6c56e9802fb6346db58bd5daf160f9be,0
+6cb2908fd789700db727dd96526bc342,1
+6cf71f5017945c9dd8bc0f5126eeef5b,0
+6d01b46b619b9f6d8c78dbd3f6864372,0
+6d38cc9a6de069570a5d2efbb55a7f63,0
+6d60c26d7d35ffd967127b380ff01c12,0
+6d75fe2462284150249a04d78781189e,0
+6ddb331865608b8dfb8cac6d873eaf62,0
+6e3a7f8ef70e26252d25cc105a945f86,0
+6e5f12931ef179cc21382a59f5acab86,0
+6e6d5603fb8fcf523f86ac0856e50236,0
+6ee742b62985570a1f3a142eb7e49188,1
+6f38eb7988753c6a978d0da80dbc014b,0
+6f43af3f636f37b9695b58378f9265cc,1
+6faabf4152bf0ebfd91f686bc37a1f16,0
+6fd3af9174242c1b393fe4ba515e7a26,1
+6fd582d25eeb2250c2b0996c4216deb9,0
+700bdc2723c2ac75a8a8376d9ca170ad,0
+70287a7720e0d90249ac7b3978b7ca40,0
+7050f8141e92fa42fd9c471a8b2f50ce,0
+7051fc0fcf2344a2967d9a1a5478208e,0
+713d8136c360ad0f37d6e53b61a7891b,1
+71665cc6a7ee85268ca1da69c94bbaeb,1
+7180c83eb184d5c9dfcbda228ab91213,0
+718f43ecf121c79899caba1e528bd43e,0
+71e09cd11d743964f1abf442c34f2c9d,0
+721949894f5309ed4975a67419230a3c,1
+722429bc9cb25d6f4b7a820c14bf2ab1,0
+7239b3a904f39b25c4e303c10a24621a,0
+72609c2be68be9d7c9cde3d0127c05ac,0
+72a1e35c34052e163f61585ba0c9daf4,0
+72b080b50118e9ddb795890eb1f13684,0
+72ed4046708e5607eb0a5703905438ee,0
+72fd04cf3099b148d9ad361efb988866,1
+73280f6a624b3bf7a766c70b31dfc56b,0
+733205c5d0bbf19f5c761e0c023bf9a0,1
+7367ede966b44c6dce30b83345785671,0
+7395f64fba89c2463a1b13c400adf876,1
+73b28e2eadad587c9a8ac6c7186dd51b,0
+744bb5ab2a706c8070a3f5cd72848ccc,0
+7471f583e1fb0e34d9e582c313af4358,0
+74797049e8df8ed38947fd38840b539d,0
+748bc72733efdabb4c239afb612bf7d5,0
+74b1b748971c474a8023f6406c54b18a,1
+74b3ef4c2125d636980a19754702dbb9,0
+74b542d34b61740c1933d2c953403aa6,0
+74b68f9442209bace31aa62027fbb79a,0
+74dca439eb5b6dfa5e33c6d2119630ff,0
+750680cce371800ea26576b694b32dc8,0
+750c11a0a87833e0bb26441b52b51399,0
+750ed950a05e5fae10b4d25ed9bcd021,0
+75150225ab1f5d910bc64ad68ea4d221,0
+7525f0ec0999007a0bac946e346eba39,0
+7577cbd6961b0cab27f88727dcd2d6d3,0
+75aef267ad112a21c870b7e2893aaf8a,1
+761aeadb65fb84c8d04978a75b2f684c,1
+762d3d698144370d197a7b9bc978d6c9,0
+763ce10dfdd4662f15de3f5931d5534b,1
+7692b05abf70dbac5292e91918e98913,0
+76a77d945cd4c568f3b602957e1ec031,0
+76e54792d7f5543f734e0906ea8f36c5,0
+76f36ea4858c572b425eb915e1b27c8d,0
+76fff2029e577190ce0bf070192b889e,0
+77033e4c1591403d1b1255607a20a983,1
+775c5f8043e72b2284b5885254566271,1
+77941d758eae521a00ef225e306eda08,0
+7797bfd33eb9f06da2b2f5d5c6501af4,0
+77d6f5203d46073369d7038b2d58e320,1
+781cf9cc66e59f4586d9338630b95c1a,0
+7842c108866fccf9b1b56dca68fc355e,1
+78459ff46c9f3b3fa26be2a467515c7e,0
+7852cb521d7029ca08133476054e7bec,0
+787bd094dd0586ea0f51f9f8557424a8,0
+78c0a0104c0428e260cbd9e50eb7eea6,1
+7917af5df3fe5577f912c5168c6307e3,1
+7921bbb92d5390784f3ba046be0d59a3,0
+797d6bffdecfc88e990e820dc5771a0b,0
+799b283083f1b6547d558f063b318e78,0
+799c0026d66479f7447ed0df5955f051,1
+79e0e507b1cd1d0c8107de4fd6b9e444,1
+79e7773230a96a6789c2c64ec39312cb,0
+79eb6f0a80841d6618968362dfb1f57f,0
+7a705cc36536145911a2ef9ace7d9930,0
+7a82802a862a267d58aa2171645f1181,0
+7ae953bb9e0356d2990ee6655c8bd168,0
+7b24367c58f1737e901dde9a934d1eb1,0
+7b43882369098df840e51421e6059aea,0
+7b4d476d9414c9339269efe47840d2da,0
+7b547c5afa0c028b0e20e9a28eaeaa41,0
+7b6c63074678f65784bdc54d8d385b83,0
+7b72b604e0af8decb22021cdb92927ae,0
+7b76426f64cb4fbe3d4caa1dcbf47a2f,0
+7b84056d69644df2a9452a1746d14d39,0
+7b87e500ff88c264aceb67cf57b32d6d,0
+7bc437435c5677d361177adb80547bd0,0
+7bcecfdddd3bd47e3b36ffb05bbdab60,0
+7bd3565827be855caf938e72b3a7880a,0
+7bfba4540956c0b2c5b78b3623a4855d,1
+7c02c641324c598cd935b588189c87db,0
+7c2b72f9e0f5649c22902292febdc89f,1
+7c8aa548b813dadf972c38e806320179,0
+7d46ce019d79d13ee9ce8f18e010e71a,1
+7dbc5207b9ec1a1921cc2f03f9b37684,0
+7dc59759253943ac070ab2557c219731,0
+7df28e2253be3490208ba9a9f470ea1d,0
+7eb217c0444e5d866bd462ade5266a06,0
+7ec258e536a1e0353375295ad1b71e5b,0
+7f137d30638a87d151ac7e84eeaf48e8,0
+7f45518a2f938a92fa99658d98770316,0
+7f524231183ed193b8f2e3d9cc73c059,0
+7faa456389e1ffde464819d0b1360188,0
+7fb1c8ffd78ca4b6869044251add36b4,1
+7ffe144af38f85d177af286c5d941ef1,0
+80588b9231bb4fb7e1cddc9321d12e76,0
+80600d4a5fee7424d689ba7d0906d50f,1
+809ae218d8b4a973d11358264e4a0823,0
+80a3052f4a1b90fd38fd0def7b79b65c,0
+80e01dfd642c5aea680852498ddabd28,0
+81528d5c9ea936264bf9aa8ab4f0ea5d,0
+817a99e1a60bcf4e37c904d73845ca50,1
+81affb342fc98aae0201a6c837cfc3bb,0
+820245d8b211808bd18e78ff5be16fdb,0
+820cc2a44d87d9b3798782f7cc6f2a74,0
+820dd342da11af3a062d1647b3736fdd,1
+82289d2db2b1e33d68ba6736b21b0e43,0
+823b5f08ce145f837066d2e19dab10c1,1
+8264a875a465c029f28110c725fec283,0
+8269e2eb69b3ba38c48dd5ae6039e250,0
+8298238a27be6111214a9bc711608181,1
+82df9b029653e867e86ce9e86ca7275c,0
+8326bb56a429c54a744484423a9bd9b5,1
+83463d2951670b7e8c3efd7594a13e10,0
+834dd009c49e7faaf8e4caba668a2d8f,0
+8369f716ca2d51c934e7f6d44cb156e9,1
+839502f9ff68fd778b435255690f3061,1
+84402e42c992259ac8cdd98b51d4fba3,0
+844032970cb66839f748512acba0be8e,0
+84876a50f52476bcc2a63678257ae8b4,1
+84a6c418d57bfc5214639012998356d4,1
+85059119462b510aacb6da54983addcf,0
+85746d90494345e38ab61533e999b3f1,0
+8589428b683d33b99557d7d3b43a518c,0
+85d59b470b927e825937ea3483571c6d,1
+8601f5424bcf4cd8e7bc3d649e9995a2,1
+8615d91dab90b906088e4097fc822820,0
+862d1d80391d146b2cd02478a798b365,0
+86515f063b3a30af09ba4d0322edf7b1,0
+868b024d9fa388b7ddab12ec1c06af38,1
+86b3b918b2ad15df1133b52f418a7386,0
+86ff28a92989348192783795a5b442e5,0
+87b81bd007c5b23cd0c0aeca722fe52f,0
+87cdb87db24528fdb8479220a1854b83,1
+87cdf4626079509e5d6d3c3b6c8bfc2e,1
+880980cc7e88c83b0fea84f078b849e3,1
+8815efa67adb15b2f8cfd49ec992f48e,1
+882107a204c302e27628f85522baea49,1
+88523579f4e325351665753e903cfdf5,1
+88ae66cd575c45ec5bb0f1578e2f1c49,1
+88be713eb83cec7d31c4553ca05b2019,0
+8918c484841c5d0a532fe146e9da61bd,1
+893fbc465b9d8a25569659a2bac154ef,1
+89629540f3b3cbc2a18d9919facd34d0,0
+8987df2216ae2ab1a907d52bc9dc540d,0
+898bd4c517fb9cf94c7d06dae56b0136,1
+89960d9a801625bf76e9e1047acc5cd5,0
+89bfbba58ee5cd0e346cdd6ffd3fa3a3,1
+89fbce8f7fe8ecc1bf7067a292c7ab2d,0
+8a17bbe3cc0079c6d7d7579359bcf565,0
+8a1fa06a0099522730dd3c12c9b9cc78,0
+8a2de07f6e9dbb8c6e4bfad7e83b3f0a,0
+8a8419bb3048294f69a31de36cd35a98,0
+8a97ff581c17a49a3ef97144efde8a19,1
+8aaa3a09b1f20e950609a62a1de511df,0
+8ad1af382994ce945a5034fab202d402,0
+8b6e16b4e1d1400452956578f8eb97c4,1
+8bbad07d91788b97cf894a05a152d291,0
+8c22afe3214768d4c585580a2364614d,0
+8c2f9e7025d6070e9f4ab8a65c8e9dbb,0
+8c4d81d9d24d9d66e9ced5f40d07960a,0
+8c5288b86ffcd597f10d639e9948411d,0
+8c63c8ebd684911de92509a8a703d567,1
+8c6f2ce60479f73c257173911aff3453,0
+8c7b03ed7f61c7faa5a26e126d769404,0
+8c9925cf3627cd4742bbc8677f905afc,0
+8cb4c49a88d8ecb99d97cf5d707d58d7,0
+8d5c4cc78e964463699c19003be70851,0
+8d98bf96ed8555da4df44f26cc8426bf,0
+8e0624a689e8e02dbae149771f51f8ca,0
+8e7638040431e1d91dffa4497f7078d9,0
+8e92c4db434da3b8d4e3cafce3f072fb,1
+8ed68f2dbf103a4bc0fd8708d8c1ac93,1
+8ee6f423ff988d10f2bb383df98c1b2e,1
+8f0c4220a437192a30ae06d82bf78885,0
+8f0d9699a15acef00da458eceaf0c846,0
+8f28d220d960b67f799479f319373c21,0
+8f4c97d428c70831d74660bca08961b9,0
+8f6e50767b3bc4367bfe551b0ed73773,0
+8fe50e522e082c3752a0814da32f7e4c,0
+90409f7fcfec3581033559f8340e48a9,1
+90604d9cce6ab054664c8efa7ce61b20,0
+90d6324d7006a3d142ee1884279dcf9b,0
+90e3b396e1c1343a514eb5890833d3d8,1
+90e5f4780b2f05136ff5f776a5cbc2af,1
+9109609020945cfc237125dc5f43f7b9,0
+9139a5b2f18c79a75c2d8ee817cc2495,0
+916ab7b22affc5651abfc9aae01bb355,0
+919b9f74bcee297abd6e217d185a025d,0
+91d0606b85ab7dbc7bab718c1312f2df,0
+91d29bc19205f8eb9a63de5b774a5575,1
+91ee390b30927af8804d1f2adf2aefa8,0
+92286959d1899e9b480d29c545cb1e0f,0
+92abfd85dd6afb639e9a8b60aaa08262,1
+92d5f6230c3b6f6256e57d30981c1aaf,0
+933cc0dec1c737d9654820453ce64284,0
+934bc93ae41ee1d98c7c44d483327f8d,0
+934f01786c3bdf8eeaf7d8411a3a8f82,0
+935908ab6e4c329756638887f2dedca2,0
+9397a41c9e819a92eb5c86e0e652d7c1,1
+93a6f37a72f60498986374f57bfc30c4,1
+93b60dbb5cc3fa4c4cc9247cb1143a09,0
+9437f7c26ffdaca5a9ae5302d9736c35,0
+9462c59a652187dc2d581b8772bcb3f0,0
+94cd77da118cc1d667cd9732853f0c48,0
+9560214767e1257dc97c5103a27f1d2c,0
+9569bb8d5fc4461461078b2e2ca29f1f,0
+95a27273c11db8bfb9fc27b1e64de6bd,1
+95edad4544e59e37188dd33db40cecb7,0
+9626af3a0a37c4fa5187447f01aa69da,0
+965fbaad39ecdaf8a135f022c8ddaef3,0
+9660e4a23b8dd7d5056a622ee3568a41,1
+968808e60982c76366088b4db7254671,0
+96acca47671874c41de6023942e10c16,1
+96dce4424dce5451ab0a068c58435c1b,0
+96fdfdfc4417d5bf8e6750edbac8ff90,0
+9703fd051751879432975535663150da,1
+9759889dcee7ed0043d06e03fb44060d,0
+9759a365f7a8b828e964b0a53cc2daf8,0
+975c90ab2afd216efbb6b772a22ba3d9,0
+975f7f3c5bad9e9f0bc31e723fd6f793,0
+97967da068bd4ee2d9cb7558f1d8c18c,0
+9842a3b9dfabab4ae8642d9953058ce4,0
+98bde8f061ae92dd23b0708fdf41381e,0
+98ea0b7d586e5e888e31633772f4df94,0
+990fbe3f0a1b53878669967b9afd1441,0
+991a2fe88aeb9ef23bb011e3843c9105,0
+99579bbe92d0bb4d5cd98982305870af,0
+99ce8aa6c0afe0e418f49823f8639776,0
+9a3174ffe867f602ee82c512a01420ee,1
+9a5c2aa17362a58ae8adcb4e0a46c7e0,0
+9b259149a750af0c21640624e4be964a,0
+9b4f0020e407fd7f980f4241fb6ac7ce,0
+9b7524785a9bf40f0651deeb3b05b75f,1
+9b797e680158d10e5ae2f9166c1dabb4,0
+9ba5fbcccfbc9e08edcfe2258ddf7178,0
+9bf3ca649999bc6856ad9f01c64eb7e4,0
+9c779a4e5e56c77131f8e99d5eacb766,1
+9ce92cb785c9878389bd5f765a07e1ae,0
+9d44fcc8ab801ac9244da4c016d0541e,0
+9d453de54a141820fcf62bed9a53540d,0
+9d89b32f7dea356b2d35cead7bc94d80,0
+9d8bdc380b51812ba82a6040ef207c33,0
+9db8f95c3240b79c32af0c0bd367dd91,0
+9de4a1ebcdf1cfd8566ed1d9b63cbeb7,1
+9e249726076fa41af6766e12957a7e9d,0
+9e471e15d44721a48d8b5f4b0a160dd6,0
+9e5c2e760b94b8919691d344cfdbac7f,1
+9e680611b54f8fad7acf818b15385002,0
+9e878fd779fb4d20aaa80db151643442,0
+9e922147900b3984c9345bdda573e882,1
+9e98136d07b953c3362e0a132c8810b6,1
+9f12d2d6134af032932ed37776c6d09f,0
+9f19c381184ba62416025849c464630e,0
+9f49140c0447a0c3108ba3591b11958f,0
+9f52323d216f89d300612cfac0122d8b,1
+9f73628a5e06cfc6723f3ee2ae4b96c4,0
+9fc639cbbd749117de4980420ae52cf3,0
+a01074fefbae0234398c365adf970118,0
+a0cdb677841933136fd15257e3c47fe6,0
+a13d6c5f8f86d74e16c10cf9294bca31,1
+a14e41eea93d7667a87d458d5cb28272,1
+a15d4fd19fb32f4858f472962c4bb230,0
+a162d204827e4e89a2e5ba81cc53247a,1
+a187b24f9827de759fb86a84e9b2e544,0
+a19a122fe9a790576b57c6bd5cf9ff5c,1
+a1b021261acaa7ffedfe15d2c8380de1,0
+a26bba2936f12f19893e54b40e0759fe,0
+a2c59fd551d9c658f8469726b66bee87,0
+a2d9e657a673798f9ebdfec1b361f93a,1
+a2f41e283f3c797e85c0b9d63453b365,0
+a2fc15125f7e222b3d8d579167f4fc95,0
+a2fe50d59500281851fce256e922b675,0
+a305389fe87d54597dfad222e47abac5,0
+a32e7fdbc0db97e35aabd7c931a582ea,1
+a34714908825a61a229bf1457c21ff1f,0
+a3cb12d3b8d5c64fa55f27208fe13a07,0
+a4ae73433e63549558a3d0eed9128a69,0
+a4dc34f2731b62f60c6c390a39fe11b2,1
+a4ebf3e2861b7845845bad3bacbbaeb5,0
+a4fa7dd73e3017b97ac6674a10fac216,0
+a532c6f9405e6f3a4229ea6e04b0d975,1
+a53a4a019a24541c277e0a84301d8ec5,0
+a590753c175011e42bf17b90e3aec3b0,0
+a59b1dc7e417fea605b34a5204f61f9d,0
+a5cac127acd59505d8f1582b95f80983,0
+a6195eb9162fc40d5fa2fdb1239dd788,0
+a647d0ce63b01c9ee82fe1911ba7b1e5,0
+a654285bc604830f627687fa821d7dd3,0
+a6b7aa6b98dd87cf75a5e1f707369832,0
+a6efbb642c60022fe194da17d71a7fb3,0
+a6f09ff7b85c72ee28a9e725bb1ec652,0
+a70fd23bd8d535ffd42259cb91f4c5ca,1
+a7293f9b20e715fc78cc0b09a4feab01,0
+a73f098ed638571f8db71a20e1551875,0
+a7411bdc623413af46a30bd9d2c41066,0
+a76b682e74918492c1f2ca4c13c29885,1
+a784a51caee14229d46777f2a9770a5f,1
+a79023a82079a7431ef2496acbef29de,0
+a79e929f408cf0fe31f8e3a0904b6d93,0
+a7eca254c634f5f6e3cd0e508b069f1c,0
+a83542b34be44586e8c9f96f4fa180da,0
+a853993fd839a0ee61f2ca73c4e497a6,1
+a858e3c7cf53e0996d76f57f2210c59c,0
+a87740afc072074e6c5a2ab787235dde,0
+a88c585e7d81744eec091a6f0600bd7b,1
+a8d308b966048be67f7413daf952ee94,0
+a8e650f8494e894be06c9cee08702aa9,1
+a8f2ebe1d66b24741cac1eb465a2ff72,0
+a8ff92ed7d8cf90d24f67ba6614c3e4f,0
+a906cd7c6ad05c27216125485d2b7322,0
+a93362de52065e73e6882f0cb668d637,0
+a998534bc46d3041e00c67f44a3e0352,0
+a9c1d12dabcd5f5b13d2aad47e443684,0
+aa198aacdec142168b8de04c4444054e,0
+aa2747369e1a0c724bea611ea7e5ffcf,1
+aa477f5b9ce7ab1e886e474be5397727,0
+aa528ce110f888679a4027513aeb442b,0
+aa55708fcc8bf27b605bcd2fca0dc991,1
+aa594c8968f06fcf374e76bc9a375477,0
+aadd54d387e9be8fab53507c4cedf338,0
+aaeb75b838690ba6ba425f73b9773479,0
+ab5de6c17f4086ba09b7145178d83b45,0
+ab9e5f1718f2af09030dd33b531f066c,0
+abc4cfb4ac045b4f9a74e2dbb18f8193,0
+abc526fd74d0fdd73772bc6867bc38a4,0
+ac00af80df36484660203d5816d697aa,1
+ac3345a5a05655c6bcce7d0b226a0042,1
+ac366a2168a4d04509693b7e5bcf3cce,1
+ac4c6d832509d4cee3c7ac93a9227075,1
+ac4e4bd5633dd74c99762acdba21934f,0
+ac57a379cfea05c07d9befe8b9359495,1
+ac68eb0a3db3de247c26909db4c10569,1
+ac9c16f3f287f0e0b321fb518ac71c75,1
+acbb4e34904af9781fe089f586418a21,0
+ad5f3a8ee73c1ff4cf401746be3bd493,0
+ad7e6fe9d036ed070df718f95b212a10,1
+ad914d487aae66bcc2a7760a959d8a7c,0
+adc3bbc63d40f8761c59be10f1e504c3,1
+ae42429e25ce48034baa3dd527c7810a,0
+aea6f1621333074412b9a6acdcda31a9,1
+af2b9f7d489ffab8e3590658853cacf8,0
+af3657cf479490d027ada92b330f80af,0
+af4dfdda000c16c4cb77ea236cf1e524,1
+af6d573b8c6804e14e3a7b07a376e593,1
+af7420c5b1c47763ecb5f6e286517b2e,0
+af9a6a57d23dd1889f8d92e5b3a2ddf3,0
+afb37b10bd304fa2c7b70cfaf1f489ed,1
+afc15e047f3e127871d13e39cde7557d,0
+b022a1d30d62ef2c1f0902f1a047a845,1
+b06ccf39536d0e3e0e8c78ba599ed23b,0
+b0864a9fd01ec7c7fa3a8301bdb2d03d,0
+b0d5ba3a5ac7998791f7e484c070dcb9,0
+b1091b5af8b47f24c4b94a9d27c813d1,0
+b1184cbc6dfa46734807211f95f3c998,0
+b158f44c31f4121c865c828ff79fc73d,1
+b1786f35f31c424f6c9e3380c1c51c0b,0
+b17cb533d71d63d548ce47b48b34c23c,1
+b227e1ab3efc4b3c5148a614d01edf50,0
+b229a7697c3efcd6ab82f6f19aff8e8b,0
+b280f1f464aa5e0de843229de12fc1aa,0
+b2d6eb577e716ade61ca89b6bb3dcabb,0
+b2f99ba5baa498246add63b1acf62cd4,0
+b3854df98b8325a98f7b48bbaf24bb02,0
+b3c2d92976acd67a13493cdff1ec33ce,0
+b3f57de0b4ad4dfae87698ef8fc67e23,0
+b42263b9b84f10464a94092e0cdc13b1,0
+b4581f4f4cad292b5a013d35d1c39f24,0
+b4d7268f5a8436da6634e585db3e9478,0
+b51f22a84cd2fae1de8bd1eb155933f7,0
+b53168fc0e9800e06de66f53daf9c5f9,0
+b5c041f7d841532ef778fd5e71309cc2,0
+b5de57869d863bdc1b84b0194e79a9d3,1
+b61b1911d3631bee521fcda3a3e568a1,0
+b635cda3e75b4b7238c18c6a5f1858f6,1
+b6578699374a9954b9a8a9e7da2603b1,1
+b6687898fe385b68d5ae341419ef3fdd,1
+b6d8dd834f2ff1ed7a5154e658460699,1
+b7045ebff6dbb0023087e0399d00b873,1
+b769e3486463214cf631bf7ab6655801,0
+b79126e0038faca869185cfe49a4e163,0
+b7ef0e864365220b8c8bfb153012d09a,1
+b818f0244d2adb13520191eed99e4680,0
+b8276dbece0182602d2ae0c825dfa1b4,0
+b83ce5267f3fd41c7029b4e56724cd08,1
+b844a9510fc4021d9603cdf24cf0545b,0
+b84c43bed6c51182d7536619b747343a,1
+b887defbf88deb3c6fe4c22405d0a957,0
+b8ad1b45ae4ba6c97951ed30b8640f6b,0
+b8bb02d229361a623a4dc57aa0e5c485,1
+b8dc33b670bb078d10954345c3ffbb3a,1
+b921bb8f821ccab27ab69ea94b8149a7,0
+b947a27711c94dda2d13e7410285cc0c,0
+b997943f8b95d72ca9a3c36f5c695412,0
+ba05599872742ce748e2eda745e51857,0
+ba162711fc958842582ef1828d37f8e0,0
+ba71b330a16e8b4c852f9a8730ee33b9,1
+ba8912fd754683662e542f8e737d1230,0
+baafc60a08ae90052fd44eb78a21cfbf,0
+baf842dd446ce9d7082efe16d22fb971,0
+bb0a8375885408a7adbd7c941098548f,0
+bb4b43d0dc4d9d2b61150df6556f6490,1
+bb8393e219a2d5e3f8a183da638cc210,0
+bb94bc5dd4656a2387bafb6098311175,0
+bba773fb9c1c517e23efe05e283b58a2,0
+bbe21f027a1df4b07016b474b48d3f65,1
+bbed0d350caad0e19e5b0fc858097ce4,0
+bbf958c2331a553d5699a1369b7f2bbf,0
+bc28807c545959c0e6e2708067201caa,0
+bc38f78d1194f57452f6bb5eed453137,1
+bc43e8a2cb05a45e73dea8c7e02f2cc1,0
+bc848c4d50c2f72fdcc1102475b56525,0
+bca9f24f465ae61a03e35a1f682270bd,0
+bcb416e94f3505c120a54dbfc0d5a234,0
+bcc701884a32d8883b73b5844241a354,0
+bccbc10909a55c0f654719e8839f530a,0
+bd5bc5a0328033ae48da9e5891704c1b,0
+bd702368c252929cf701ad56ce64b6e1,0
+bd87def5b7e1ec4f0057cde049995d83,0
+bda661b08ad77afb79bd35664861cd62,1
+bdb59c956d48bc1a263acf997926c4d3,0
+be024b0b5cf93c597758e65f348475af,0
+be2be08151ef4d3aebd3ea4fcd5d364b,1
+be4285333fb2d56f78ca867d97eee308,0
+be57c648eb683a31e8499e278a89c5a0,0
+beb2f21fa785f088469a4530784e9d81,0
+bedec8e1ad130a08faeec8ed81780d56,0
+bf1c730d11f5c1db7da7c39808451c4c,0
+bf3dbf9b2379ca92ceaafc1867de0422,0
+bf56e271a2aa37625192954157e9f64d,0
+bfb3e2d11c149036bbe12566ef6b933c,0
+bfdf6f821031435d9a397afe001ad774,0
+c004a9415539a0bc98c42c1a444cedb8,0
+c020f5c28fc03aed3c125714f1c3cf2a,1
+c0279b938ac1790f1badfcd4459f5c4c,0
+c02daa2116b27ce9b023fe7809ef5be9,0
+c05acf3bd59f5570783138c01b737c3d,1
+c0625c79ef5b37e293b5753d20b00c89,1
+c0712bc73239d89cddd71a93865e2946,0
+c0a71c28edac0a4bbdf64f058903c4b4,0
+c0f0eb84e70b19544943bed0ea6bd374,1
+c0f2e3b499d10d147892579d0ad71321,0
+c14816a1a9a6852c6b0d88fe5585c8bb,0
+c1673993c070080c1d65aca6799c66f8,1
+c187d7be84f64e29e6623c15575f373f,0
+c19197af81f94110ddc23317e182f37d,0
+c1ac4b0949e6e7557f82caf20761322d,0
+c1ba619e3b49e0cb7798bd10465c2b29,1
+c1da930ea00f6d11bab7dd34014b7d6c,0
+c1f5ca42b0e336a7ab85b4c437b382c0,0
+c24798432bb6a0d4c80df831b8e09246,0
+c24dfc6534bc563d5aecb1513fea8f7f,0
+c26fbd6a185271f820953be327b5307f,0
+c278a6dc82c323254ff53c58db759908,0
+c2878958469b61d4f4406bbe945f8bd7,0
+c2af7c1d6159ae152a79f32d88c33ab2,0
+c2b4ac9d22e601c5d546318874c76f59,0
+c2bdfb6ab5192656b397459648221918,1
+c2e546795f1ea2bd7f89ab3b4d13e761,1
+c313167b76fb2528816d40088ba88c77,0
+c31e3540b227a1a2b08593094609ece2,0
+c3b05094939cc128a4593736f05eadec,1
+c3d37bdb061c189269f4223f8bebeae0,0
+c3e23e84b9f9f31c3ba5458c7f43ec52,0
+c3e6b43c5ac3f4ac052e0b0421f5b088,0
+c3e8db4f544e2d4ecb01c59551eb8ef0,1
+c4c801ae039ba335fa32df7d84e4decb,1
+c51d53068736c39d56b99074d2e29e12,0
+c545ccf3a5128fdc313ed936f61658a6,0
+c5887c21bafb90eb8534e1a632ff2754,1
+c590651cdf70258ffb1b6ee18da6a1b2,0
+c5f73cf44d785e5ac2e7f0a8897f683c,0
+c610439ebef643c7fd4b30de8088bb55,1
+c6269c87a7571330961e5c4a9f692c10,0
+c645eb8b7b7225457e61cf511a8e46e5,0
+c65cc99faea7d0f79c175460c712f375,0
+c65d665029c9561bc408f3651c3e2db2,0
+c67de8fbbe1e58b464334f93a1dd0447,1
+c67e799bcc1e2635eb9164f6e8cf75f3,1
+c68ec9a72b87f4bb7935534182145733,0
+c690f27c439a58684910d04d6409cd17,0
+c6b722b00948587dd89a548f9639f447,0
+c6ba816fd9c99c11ceb189ac24d2d2f6,0
+c713ec80637677965806579fce0b7dca,0
+c7729e1c348f7d54d743388767c69cb4,0
+c7b20bdbf5f057ec1e9706ca43bf9a2f,0
+c82d5bc4554358b1512f9f871822705b,0
+c84e28d37dcc14a268b760bf16213cfa,0
+c8594cc837b12c612d8b9a0913240f8a,0
+c8a82a4e7e76702f5f10ece6508f2bbe,0
+c8cfb917b0d619cb4e25f789db4641f8,1
+c928b4fee44ea322ac65348ae2ff20b8,0
+c979fbec565e769de7e66944ab5365a4,0
+c98675ecb5bdc7eb35c69d730da05df1,0
+c98fb8f387c0979531e11de53607de92,0
+ca3cdb2e771df9989df5a9cb0296c44c,0
+ca4e1486c548679a9c682b6fa1a779d9,0
+caa6c81b74054858772bda6c2a0e8ee6,0
+caddd8f856b110ed9bb52872e003193f,0
+caf38dcf62fe3a05fac40055920d7058,0
+caf5e9cd994c3c90727d274dd790133a,0
+caf9672e7177c141dd3d9c8631af6b8d,0
+cb0110b3780d2cf1134221404b82713a,0
+cb64ff663195832e0b66a9bb17891954,1
+cb8d3452b667596fbf132d2ce9ebd0e6,0
+cb94c3f894fc93c1ec0eb436c8564ed3,1
+cbf5f53f3648de7d1324257caa40bb90,0
+cc1bf5250466173086887675dff499c3,0
+cc24c86f88a9d17c04255a4d264030e6,0
+cc31a959bf4c2a6de3a67dfa378a261c,0
+cca8f8cc51b58df2a4804a7aee8eef8c,0
+cceb1ae43615e5f144e31d1d1ebbdf90,0
+ccff3e86a50624e30c22d674f3b0f9aa,0
+cd104ad99d5b939b6bdd28b154e28085,1
+cd10ceca9862ba0cc2ffd0ed8c9b055c,1
+ce0609052ba7b533e2974728b0c76bfe,0
+ce8b0816304e079bb99c6c25b4fa4b88,0
+cec6819833f63e96fc3e17e29c0124f8,0
+ced4f41abff9290b0638b0a25cd5a26d,0
+cf0a772e90a14d77d664ce9baedf0e5c,1
+cf3034c8828df3c2c23fa697ffde07fa,0
+cf34926681dbf1129cb0a629fb72681b,0
+cf83e9933c484dd9073ed8314794b9f7,0
+cfbcb16fea277226d6771d8b1966397a,1
+cff7e7e9f8cb7b37c109ed6b1f11b783,0
+d00ee8f03fb00562b2db35e90536ffc1,0
+d08383958039c53ea3347ce1719be43e,0
+d09e4124b97b22ef45692b62b4ca7f03,1
+d0baf38ff8d974e7b59c23fd43713de9,0
+d0c1c175814c610bc333080152a605f7,0
+d0c86e0c3b3fe3e1dd936b7553ecc29c,0
+d104e584e51830ea51ee60e69186f83b,0
+d13d9be7873c99a9fde9d24a95f1590d,0
+d2282b0eb61b8d3b090cf8eb76776529,0
+d2285c33945ab3421d753b4fc59ac3ce,0
+d244870d213a21efa86e86c951d8c9a2,1
+d287819450e57ae8c883ed31dc4dc3a3,0
+d2a17180c72ce7e5e9cb3870ba7991d2,0
+d2b47d9034d38a410f00dabba9754d91,1
+d2eecd9f13a6d474338045d0c91cffbd,1
+d34741458ed4cf1ef6bcf3da21a0c47c,0
+d36b2cb1cac4b31476c6f86eb1227d3c,0
+d39d18ec79c7303a61f778f470d439ae,0
+d3aad463ed33cb02334f0c3029db4587,0
+d3bc6721c1b0830137515e9c0c31612b,0
+d3eaad692dc96b1a1765076716f55421,0
+d421129acf503e770dc1575c1b959607,0
+d4307a302483bcc04717ca4f565db678,0
+d43c9dd1be361b9302c9343af09cc23e,0
+d459ff0332d2b10be26eee73b1f80f7b,0
+d4e5c5bf1871b85914168ea12ed579a3,0
+d51dffd06b80ed003aa6095b0639f511,0
+d559c9b1f2be30c82f8dbe4d73d67bd2,0
+d5c43054ba0f66d5017a8ddfde8c8c34,0
+d66d6279f6a55d7263e2700749b4293b,0
+d68bfca920fd548909bd9c7eb5694b9d,0
+d6d5ed3055d084a6abf0f97af3fe2ff0,1
+d6fe4bdde1a2cc3dc4efe22becfe22fd,0
+d73264d2c4f71ef6bf8593ac55565d93,0
+d73fda3be1180e4465df6fbef8a0648d,0
+d74af71db9023b65737ee37ede219422,0
+d7713d80767cfdaad5e3db537849d8d0,1
+d777a77cc7a2ec2f1eed68799cc9075c,1
+d7aa27d839b1ecb03dbf011af4bcb092,1
+d7e5640b52c8e092ec277febc81478da,1
+d809c513476775193aba29b31d0050c6,0
+d81704ee56c124cc1434640918a3299c,1
+d81ab3ad896e4198caed105c469a4817,0
+d833b4c1530183c1b3eae02e9a2cd735,0
+d89499632a4c7bde0923003497ffc5ea,0
+d8a0ebe575539c2357c2365cdf0229a0,0
+d8ed783494996f55a587270a212f7d5b,1
+d917c781760710015473eee9ce82e051,1
+d92998a73d4654a442e6d6ba15bbb827,1
+d9543b86db1c662ebaa71557e715861c,0
+d987c00ec5463a0a696991b72d934512,0
+d991b1760fb8705de655a1da068f7a6a,1
+d9a2bea7df4a888313374beb142cf9c0,1
+d9ef71a00fd504eac1a6dd104c93ce56,0
+d9fb9617188fe99bdb464c126d2bd8c0,0
+da821546432756d377777d7f4c41ca2f,1
+da8fea00d3e921e5d8ab4d90a7f6002f,0
+daaf7680aa9a2b519e53b0e38300163d,0
+daee58dd09c005fe41ca370c2a2fdfa9,0
+db7c113445db32f9beaf5dc90e7218ad,0
+dbcb3dbee4f4e75d0672c2a23feb1e3a,0
+dbfbc12c7a943a2dc0e34bfd4a636bca,1
+dc1ecce5e7f8a4be9082cb5650fa62bd,0
+dc5cd907d9de1ed0609832f5bf1fc6e2,0
+dc66d11755fd073a59743d0df6b62ee2,0
+dc9854bcdcc71b690d9806438009001d,1
+dcb426dd025b609489c8f520d6d644b7,0
+dcde02d4757bb845376fa6dbb0351df6,0
+dcdf0b64b314e08e8f71f3bec9ecb080,0
+dcf5fd36b9fff9183f63df286bf8eef9,0
+dcf75f484b2d2712e5033ba61fd6e2a0,0
+dd281294b34eb6deb76ef9f38169d50e,0
+dd571c3949cdae0b59fc0542bb23e06a,0
+dd5764803d51c71a27707d9db8c84aac,0
+de04fbf5e6c2389f0d039398bdcda971,0
+de4d3724030397e71d2ac2ab16df5fba,0
+de635c85f320131ee743733bb04e65b9,0
+de881c07adc8d53e52391fac066ccb9f,0
+de9f65a7a70b73ce2ffef1e4a2613eee,0
+df015da931ad5312ee7b24b201b67478,1
+df1354de25723c9a55e1241d4c40ffe2,0
+df54dc42705decd3f75ec8fd8040e76e,0
+df75d5a21b4289e8df6e2d0e135ac48f,0
+df761dd787bfc439890740ccce934f36,1
+df8614fd49a196123c5b88584dd5dd65,0
+e00832e96709eb85f8e0e608ca02c2b5,1
+e10c2b829c39d4a500c09caf04d461a1,1
+e127111e994be5f79bb0cea52c9d563e,0
+e129305f6d074d08cd2de0ebdfeaa576,0
+e1584618a0c72f124fe618e1ed9b3e55,0
+e163325ccf00afde107c80dfce2bce80,0
+e188bdeea72bb41d980dc2556dc8aafa,0
+e1c92d3f85a37bd8bb963345b6d66e03,0
+e1e47812eecd80466cf7f5b0160de446,0
+e1f3a01e73d706b7e9c30c0a17a4c0b5,0
+e2a7eaebd0830061e77690aa48f11936,0
+e2b7fe7fbb002029640c0e65e3051888,1
+e2bcbfe1ab0f9ddc5d6234f819cd5df5,0
+e2ea2f046495909ff89e18e05f710fee,0
+e3034ac9c2799b9a9cee2111593d9853,0
+e3423505ef6b43f03c5d7bde52a5a78c,1
+e38789c5eabb3005bfb82a5298055ba0,1
+e3a9a6f8d21c6c459728066bcf18c615,0
+e3e518324e1a85b85f15d9127ed9ea89,0
+e414153d0e52f70cbe27c129911445a0,0
+e42815372aa308f5943847ad06f529de,0
+e43afa905c8e279f818b2d5104f6762b,1
+e4421d2d5318845c1cccbc6fa308a96e,0
+e4436b5914162ff7efea2bdfb71c19ae,0
+e46973b13a7a6f421430d81fc1dda970,0
+e4a87107f94e4a8e32b735d18cef1137,0
+e4ff18b33b7110a64f497e177102f23d,0
+e537c91cdfa97d20a39df7ef04a52570,1
+e5438d842118e579a340a78f3c5775cc,0
+e54b574a7e7c650edc224cbdede9e675,1
+e56b9f25a47a42f4ae4085005c46109c,1
+e572e978c2b50aca781e6302937e5b13,1
+e58b78dc31d80a50285816f4ecd661e3,1
+e58cc57cab8a1738041b72b156fedc56,0
+e5c68cfa0f33540da3098800f0daae2c,1
+e5cf847e616cc2fe94816ffa547d2614,1
+e608c0e6cf3adf3c9939593a3c322ef7,0
+e6214ef879c6d01ae598161e50e23c0c,0
+e63f43056330bc418a11208aa3a9e7f0,0
+e659f6517c4df17e86d4d87181396ea6,1
+e67bc6cd24a71a486b626592d591a2da,0
+e6b3e750c6c7a70ca512d77defcfe615,1
+e6d4a747235bfcc1feac759571c8485c,0
+e6d8b2631843a24e6761f2723ea30788,0
+e6f4757b8f315f31559c5c256cb8dead,0
+e709901da9ba15a95d4a29906edc01dd,1
+e787e5fd289a9f1f6bba31569b7ad384,0
+e79f52e833ccca893509f0fdeeb26e9f,0
+e7adb2e4409683b9490e34b6b3604d9e,0
+e7cb27a5362a7098e1437bfb1224d2dc,0
+e7d76f0723911280b64f0f83a4990c97,0
+e858263b89f0bb57597bcff325eaeecf,0
+e8be143b9f5e352f71043b24f79f5a17,0
+e8eb842ee04bbad407f85fe671f24d4f,1
+e92a2ed80510513497d5252b001cfa3e,0
+e977737394cee9abb19ad07310aae8eb,0
+e9ccf1ce85c39779fafb9ec703c71555,1
+ea7373271a2441b5864df2053c0f5c3e,1
+eacb38abacf1214f3b456b6c9fa78697,0
+ead64f9269f2200e1d439960a1e069b4,0
+eaf753dc137e12fd06e96d27f3111043,1
+eb008af181f3791fdce2376cf4773733,1
+eb8d5136918d6859ca3cc3abafe369ac,0
+eba18d04b18084ef64be8f22bb7905ca,0
+eba4bfb93928d424ff21b5be96b5c09b,0
+ebd601d40a18634b100c92e7db39f585,1
+ed0f3c1619b2becec76ba5df66e1ea56,1
+ed49b57854f5580658fb3510676e03dd,1
+ed83b655a1bbad40a782ad13cf27ce8f,0
+eda58f4918c4b506cd156702bf8a56a3,0
+edad1a7e85b5443e0ae9e654d2adbcba,0
+edae2e1edd1217d0c9e20eff2a7b2dd8,0
+edbf53a8478049de1494b213fdf942e6,0
+ee71210fa398cbb080f6c537a503e806,0
+ee88217bee233a3bfc971b450e3d8b85,0
+ee984e8fba88691aac4992fbb14f6e97,0
+ee9c580272cd02741df7299892602ac7,0
+eeb1659b92b00e20bd8b6e7eef6b5c9d,0
+eebd87b91489548bdfc1c76a20999a54,0
+eed4db0cb0576c274de569e98a56a270,1
+eed63953a76074dd5ef7360e131f4852,0
+eee8e1b2533abcb73e4b03969a3a5904,0
+eef0e41b1a96cf8c55723fa6aa2f3dc6,0
+eefc3f380cc72d6fa830972151df01ad,0
+ef3be197823bfa8c6976ca2621e253d5,0
+ef6a37afe024d33b4b1bb2fdee054a59,0
+ef8a19fb5314b3222482fa325dd49467,0
+efd5b9e8cb651e18eba6a9623e36e7be,0
+eff5b5a7c7245fa8f4661d7e88f8bc7f,0
+f029c73f6f8753e7447c4e9f22e917ad,0
+f0459473753b99105e9723f122022ad0,0
+f0f72264cd822301852578cc71288d3c,0
+f136a3df63637b499704a49fc0e3dfaf,0
+f17867cc3e579dc2fc6f0334bc43a91d,1
+f1a64fda219db48bcfb8ad3823ef9fc1,1
+f207bb8bcccdc76143380849402a4f21,0
+f228862e9f9c6ad7993ded4e088c5050,0
+f243bd277f1876a77a0fb18f9092105a,0
+f25c425c827b35fcbaa23f2ed671540b,1
+f27d7bf8df3cf0cd187682fc6860b755,0
+f29d00ddf6d9846aa600c3f0edf5f952,1
+f2ca85bb9ae82a3d79b9f321f727ac19,1
+f2e952758095bc50691ab02f724568d2,0
+f2f23b265b2a3b977cb81fe3193d7c2c,1
+f37d1d5c299d4838b294cf82902675b0,0
+f395ca14ccb03ad40e98d1473cf686ef,0
+f39a1e54d79731e4417aa8159d19b7d4,0
+f39dacd5f134f3f4482094d3f8a0aff1,0
+f3d40bbf94a7951dee3b0028e301a126,0
+f3eafe72b1e9528116f3c430ab73a2ae,1
+f3f6f40ccb01276d722d52701cab1754,1
+f42a0343e5b5154c6a184fc955d8f20f,1
+f43843b39a5be8cd30dab59bd11499ed,0
+f447ac9884a349a4ae56326cf680ae18,0
+f44dd045f6dcb1e477e6d3dc0f29d7e8,0
+f467795ce3b50a771085d79ae8d29ecc,1
+f4bee414210374e68b6746f70b38d461,0
+f52bd66210db45189027991781e1162b,0
+f55b8ee990408001671d76c3595afacf,0
+f55f99177e8b4b267c71b4e5fa4116be,0
+f5630f467acd9aa977b61a3e5780c2eb,0
+f5713e8c98ef5378ea678fb8d9192e13,0
+f5717f7cbc08d8bd942cd4c1128e3339,1
+f599c9bb0bd19126e13fba8b63d2de41,0
+f63f2f63e2619012b4c798fd638c8b8a,1
+f69c80f898c9dfd8d3595b7ca7b8c66c,0
+f6a2e171a3be579b564cd855985ab9d1,0
+f6a9611b3afd5c6a5fb4a718cd2c38c2,0
+f6bf2c352e3c5b13ae48f077570f3d15,0
+f6c9e875d7adfe7add08f43528810f72,1
+f725f46908f16062fd12c141eb47c6a7,1
+f73624b8b22774acf9a3e2c748131eac,0
+f74cbe4dda0f80dd66e15e64563689c6,0
+f76143416ee2c8e1251f45f108fed468,1
+f77fd9fd7966b346ce8e7efcb96c7c53,0
+f78944bd1732001a3c62723a8cc19856,0
+f79681d8561b6443a5b95f78f3ea6411,0
+f7a03adba817f2a2249b9dee0586f4be,1
+f7cdd95c94818875ece1175561025038,0
+f82560aeea0309873716efe3aa71ef0a,0
+f83c62177ee552891d22df33be12ab07,0
+f88ed45f3436cb30e494409dae76df5d,0
+f89a08a93f1ceaccb0cba52156fd6f03,0
+f8ecf6be8ae631c6dd694c9638a02b45,0
+f8f66fca04d2e67eacd86ea154827a4c,1
+f938f9022abf7f1072fe9df79db7eccd,1
+f9ce0c5ded59a58b9d7ca5200e6b1182,0
+fa45178d023325b255a3d4fc3e96cb7d,1
+fa744c0374ccc6aaf6711f463a9e5bc2,0
+fa7bf17071e3234ab1f350341303b174,0
+fa9575f64e6881c6b2730f0e225c9573,0
+fa968673987cfd078d91641294c3bf63,0
+fac65dbf7b6972049cfd37b5b122ec0b,0
+fb52dd8152e53a4ca7da5403d6d0db13,0
+fb57fc6377fd37bb5d42756c2736586c,1
+fb7ae70f05b6441ac4ea7187ce7c45f7,0
+fb7dfb6aae597d97c2da24179df0fe56,0
+fb99a80cbb2f441bb90135bab5b029fe,1
+fbaa8548e6c3753836579c7987d0034d,0
+fbae4d04285789dfa32124c86586dd09,1
+fbe0c3d6e4a50ca1c1bd3101515d0ab4,0
+fc545aa2f58509dc6d81ef02130b6906,1
+fc658f9bc12a751a17f16589f9e3619b,0
+fcdc2d423356d53759a8f602d40785a6,0
+fd0c2dfe0b0c58330675c3191cef0d5b,1
+fd2dd970bd3d91e5b26d7e57c03f70af,1
+fd4c2d4738bc25a5c331dbc101f3323a,0
+fd64b23b8cd8c371c8f76fbb503e4e0e,0
+fd7c0fb3c0e764357aa58e5f047be614,0
+fda187bfb1d6a2ecd4abd862c7f7f94c,1
+fdf2a2f5b86aea0da54732056fc7ab48,0
+fdf73dcce35167f3ed952a58f5a6f738,0
+fe26fd2bb25112b3c2ca93eb8e34f8ed,0
+fe45462987bacc32dbc7126119999392,1
+fe5c37e82b412833b8ad0abb57978377,0
+ff5d8e90500cf324e7b04a2f07cf0399,0
+ffe02fe7d2223743f7fb455dfaff3842,0
+026470d51482c93efc18b9803159c960,1
+031b7ec4fe96a3b035a8196264a8c8c3,1
+03bd22ed5858039af223c04993e9eb22,0
+06a90409e4fcea3e634748b967993531,0
+07b1defcfae5873ee1f03c90255eb170,1
+0b20184e0cd497028bdd155d9fb42dc9,0
+12db1ea8336eafaf7f9e3eda2b4e4fef,0
+159bc8821a2dc39a1e770cb3559e098d,0
+174c5f7c33ca31443208ef873b9477e5,0
+1753250dab5fc81bab8280df13309733,0
+1cf8e778167d20bf769669b4be96592b,0
+1e62be2c3b6430b78ce31a8f023531ac,1
+1f6333bc3599f683403d6f0884aefe00,0
+1fdbc07019192de4a114e090389c8330,1
+2004b3f761c3f5dffb02204f1247b211,0
+202898fa97c5949fbdc07ae7ff1cd9f0,0
+21b73c938fd7d346ee77a60bd60aaeac,0
+243038f7bb7787497c59bc17f04c6ed9,0
+26142353f46d20c9fdded93f01e2bff4,0
+263a1c3bfa43556623e75ed901e3fd8f,1
+2703df8c469906a06a45c0d7ff501199,1
+2a3e6ecf9499607ef4fd14b436136b0c,0
+2d596b6ead89ab35577fe625a9a17cbb,1
+2eb92d17ca91b393765e8acf069763a6,1
+2f77fd993fbd858dec3c085b9ff1a3a2,1
+3295cec04482210dc6f78c2b4a1d287b,0
+33387bea2cacf6127035cc7033036a02,0
+34037914ceeec5605fc890159dd425c5,1
+38bf066bba822584e14c0af65d4bb5e9,0
+3ee1fd6a0f3f108c3558e6699fb011f2,0
+42b2161e43b4dd0ea94604485976c59c,0
+4434e19303b62ebaecef2596583ff351,0
+4575fe61bf3f536ce6cfeb26fcc2893c,1
+48ab0b98fc7789304c21430978624f32,0
+49433c1588cc078b825a0eff1dc2e816,0
+49c88f7cc77341c9ae4e64243f9912fc,0
+4b28f147cb82baba3edcdbd34ca19085,0
+505405b3e70fb24b92e6a8a5b7ed339c,0
+50cdacec399071cf70d8badd2511d0b3,0
+519ad4ead3e61d2d71088ac8e46f25b6,0
+52f6d741e674f62fbcf73e6ec4f6a472,0
+538543b57d0c8fa0b2b6bb7c84df3f33,0
+5451203688c930484ba1f3c7f1378847,0
+55b06d60e7c0329787f81d1b7cbf9aa0,0
+567547810a1795b9c8e11c15dfd32c34,1
+5791c42d317f34592be9a933c50e68ad,0
+580cffecce8d3d53cde1abb922adf21a,0
+59af702c21840ec18073b6b56c95e7fe,1
+5a42f0a0d1e060531c20d04ed23efc02,0
+5ae9ab473d59cd29262c47a741177b6e,0
+5ce91933688cc8400105bf640ac11535,0
+5d16819bd78c74448ce852a93bf423ad,1
+61017c23bbae6e17062ff582d1a237b3,0
+616f98dab4db03edbad28c73d22468d2,0
+63458b5875a0b223ec21555d17b52fd4,0
+6379e4435f78a5e5c150c32146ece4d4,0
+649fd56ef9809019b57261fcf9574d76,0
+665c1913d8e90e57af3b745349d19537,1
+68f4dff6dd1f135488e83b8a4ee6e20e,0
+6993396b31078993e13cf9c0a6fd470b,0
+6c71617e2cee498fd3dd20956bb90a3b,0
+6d3b16f2e60c3a1a4246f340dba73676,0
+6d3be6081d76d2365b080e599628d3bc,0
+6d43fdb6eb1bec3a5f4febfd442e8c93,0
+6e240f23afa2c1b4352cd0db5d4f357d,1
+6f229187fe608c9eacc567eb74c1458c,1
+7027c0b8c8f8dcc76c6e4ba923d60a2e,0
+70671fa94231eb377e8ac7cba4650dfb,0
+70f4eb8201e3155cc3e399f0ff09c5ef,1
+7191c236cfcfc68cd21143e3a0faac51,0
+763288341ee363a264fe45a28ea28c21,0
+7869cc6bfc3678fec1a81e93b34648cf,0
+7c2fd0d32df5a2780b4b10fdf2f2cdbe,0
+7ce310b8431ace09a91ededcc03f7361,0
+7cf1a65bb0f89323668034244a59e725,1
+7daeb8ef7307849c715f7f6f3e2dd88e,0
+7f096cdfbc2fe03ec7f779278416a78c,0
+7fd5be8ec9c236c314f801384bd89c0c,1
+80938b4f531fa2334c13d829339e1356,0
+80bda1afde73204abd74d1ebd2758382,0
+81bd0c062bfa8e85616878bab90f2314,0
+82b9fb9e238397b2f3bff98975577ff9,0
+83728b6eed98845556bfc870b7567883,0
+84ed26b5d79da321711ed869b3cad2ea,1
+85ab88f093ca53a4fab5654e24c77ebe,0
+85d6fb4a08853d370935a75de7495a27,0
+86ad341b9ac27364f03981f6a775246c,0
+88acee40bb9d8cb06898d1c5de01d3c8,1
+89f003dbfbdbd18a5cdeb9b128cb075b,0
+8a1e5830a16db34b580202f8b6dbbd3d,0
+8b494d14d835dd5ae13dab19b9520a55,0
+8b9a28375988de6ea0b143d48b4a8dc9,0
+8bb7dd5fbfa5ecb95552d9c587f2fea5,1
+8be7a7cc747365030bee8297221ab5bc,0
+8e60f166f1f1dc0d72f997fe1c9e72b4,0
+8e9002a485cbda2b47cd14014d6f1c36,0
+8f517521a2ed576e853fab1907fa5ffd,1
+8fde44df03fb80366c6604db53d3623f,0
+901ed0a38aa16933c04ffd531b0aa2cf,1
+9050cf3aa8371bd7088c4bdf967141d4,1
+9065f2b133129c5747d42db18a424749,1
+931253c408c440a8494dfaa74251efd3,0
+94df6d1ae21c5bfaebe6f8daf8fcd85b,0
+95a98df466d4f6c6689908ea9a8f324b,0
+96042e205dd3dc055f084aaca245e550,0
+96544665531e7f59bc2730e3c5f42e65,1
+96cca9d8e5764daa4bcb6c0ba07735bc,0
+993f1e68290d591f755669e97b49b4f4,0
+995fc0581ed0e3ba0f97dbd7fe63db59,0
+9a378249b799bbcefac2a7de46896c0a,1
+9b871732b3935661e7639e84a6ab9747,1
+9ca18e68b6b8d9c3112b4b69b7d6fad5,0
+9cc74e673ec9807ee055973e1b185624,0
+9de48cf43611478ffc1fef051b75dc8c,0
+a0e60d7a13f6bb4002cc4a08e60b0776,1
+a0fc609febe3eef5a4713a22996cf8e5,0
+a2558184e0f4a68e9fb13579d20cb244,1
+a2a4bc7708f6831470d757cd6f32bffe,1
+a334d15ac8d2d25bce76693b1b2a3ed7,0
+a5bb766ab3b1bc5a8023a50a956595f2,1
+a5d7909f14d43f01f44cdcaabed27b84,0
+a6c15206edadab0270898f03e770d730,0
+aa59b7a4aa4dfb2489feea527eda3e4d,1
+ab9c7bef62d1ad65b824414087b6f06b,0
+ac4056071f3cc98489b9db3aebfe2b6a,1
+ae2fdcd8daa3fede6ae23cc63a8d9a82,0
+ae4e9d8aab8f8f5ae975bcca923f468d,0
+ae61ec94b0b8de5439180f4776551e42,0
+aec5a58fea38b77b964007aa6975c049,0
+af1d0c2fcde369dd1b715460c2f704a2,1
+b0599ad2f33276e7cd065eaa8dcec8a2,0
+b17c07114dcf49ce71c8da4b43cf1192,1
+b4d5b618fdf3a5a1bcfb325a3715e99e,0
+b4db5b96c65a668a2e63f9a3ed36afe7,1
+b53d997901eb880c41fbfbc82847204c,0
+b6857d98b7b3dbe84f153617f4dfd14b,0
+b82efe72526c59a96257208d95e54baf,1
+b8793dbd40de88c0de0913abbaab0fe7,0
+bbf7a3e138f9353414f2d51f0c363561,0
+bdc2daa372a36f6f7c72abdc0b5639d1,0
+bdfb2c23a8c1dca5ea8c1cc3d89efee9,1
+be3e35bf8395366d235b8bcfc71a05ee,0
+be9a2df5a16434e581c6a0625c290591,0
+bf6a7a9ab4e18b18f43129c9e22fb448,0
+c0c5a155e6e59588783c2964975e7e1e,0
+c25876fb40d6f8dafd1ecb243193dd3f,1
+c2ef34cc347bc224b5a123426009d027,0
+c3a9046fbe2b0f0a4e43a669c321e472,0
+c46c3962c10e287f1c1e3af0d309a128,0
+c71d0db2086b7e2024ca9c11bd2ca504,1
+c7bdb83b7ca6269fac16ab7cff930a2e,0
+c87a713d17522698958de55c97654beb,1
+c95f2aa23e6d6702f5b16a3b35f89cf0,0
+cbb9bbd994c235b56fb77429291edf99,0
+cc1b7e34d9eba737c9fb91316463e8f7,0
+cc4805e3ebe8621bc94a621b1714fc84,0
+cd68d1a14cc504e3f7434d5cc324744d,0
+cd6be62834c72756738935f904ec9c2c,0
+cdb53f3be6d8cce07fa41c833488d8a5,0
+d03127f497cae40bcbd9996b4d1f5b90,0
+d032116d73789ff9c805f493357b4037,1
+d1131708024b32032ade1ef48d115915,0
+d1a20ef45bb03f93a407b492066f6d88,0
+d2ec8f0fc56a9168cda0c707e49974ab,0
+d3a8fb1da8f7a0dcbd5a8d65f3647757,0
+d42c998d037fb3003faba541e2cf649a,0
+d4a075768abe7fe43ad1caac92515256,1
+d5a0333be8795805fc39509f817780ee,0
+d654966fd2498de023552b830c07a659,0
+d753676c2c6c8ac6f97bd61ecab7554a,0
+d81852bffda09dc8033a45332397c495,1
+dbd9c8025907511e965e7abad955547d,0
+e0aa61b44c33e6a75940a8541c6894c9,0
+e314fd13809db0132443b924401d828b,1
+e33c25d0dbca5e54385f2100ce523467,0
+e3bc0a970a4af5d52826e06742f90e5b,0
+e42065c1145ccf734312cb9edbe5234b,0
+e60d99ea9648e1ce859eb0b386365e26,0
+e6160ed0ff2eb214abd4df9a3c336c1d,1
+e6d8ae8c3b0817df994a1ce3b37a7efb,1
+e9a27e2645e1fad9434ce765f678585f,0
+ea01deecde93cd9503a049d71d46e6d5,1
+ea3a771ef05e288409e0250ea893cf87,0
+eaeebb7a63edc8a329a7c5fbc583a507,0
+eb9db3f740f8e153e85f83c57bc4e522,0
+ebcdfabecf4b46b1e55e4a4c75a0afb0,1
+efcb6def7a2080243052b6046186ab24,1
+f0310ffc724faf9f7aef2c418127ee68,0
+f4d23e0272a2ce5bfc7f07033d4f2e7d,1
+f5ff7734997820b45dafa75dff60ece8,0
+f7c387290d7e3074501eac167c849000,1
+f89e3d0867e27be8e19d7ed50e1eb7e8,0
+fad57a1078ddbc685e517bd8f24aa8ac,1
+fb55849cee6473974612c17f094a38cd,0
+fb5874408966d7c6bebd3d84a5599e20,0
+fcfab3eddbdf0421c39f71d651cc5c56,0
+fdcd385b0d2d12341661e1abe845be0b,0
+ff8599dd7c1139be3bad5a0351ab749a,0
diff --git a/training/classifier/kaggle_full.npy b/training/classifier/kaggle_full.npy
new file mode 100644
index 0000000..40016ae
Binary files /dev/null and b/training/classifier/kaggle_full.npy differ
diff --git a/training/classifier/kaggleluna_full.npy b/training/classifier/kaggleluna_full.npy
new file mode 100644
index 0000000..b3ff74c
Binary files /dev/null and b/training/classifier/kaggleluna_full.npy differ
diff --git a/training/classifier/layers.py b/training/classifier/layers.py
new file mode 100644
index 0000000..939b7be
--- /dev/null
+++ b/training/classifier/layers.py
@@ -0,0 +1,359 @@
+import numpy as np
+
+import torch
+from torch import nn
+import math
+
+class PostRes2d(nn.Module):
+ def __init__(self, n_in, n_out, stride = 1):
+ super(PostRes2d, self).__init__()
+ self.conv1 = nn.Conv2d(n_in, n_out, kernel_size = 3, stride = stride, padding = 1)
+ self.bn1 = nn.BatchNorm2d(n_out)
+ self.relu = nn.ReLU(inplace = True)
+ self.conv2 = nn.Conv2d(n_out, n_out, kernel_size = 3, padding = 1)
+ self.bn2 = nn.BatchNorm2d(n_out)
+
+ if stride != 1 or n_out != n_in:
+ self.shortcut = nn.Sequential(
+ nn.Conv2d(n_in, n_out, kernel_size = 1, stride = stride),
+ nn.BatchNorm2d(n_out))
+ else:
+ self.shortcut = None
+
+ def forward(self, x):
+ residual = x
+ if self.shortcut is not None:
+ residual = self.shortcut(x)
+ out = self.conv1(x)
+ out = self.bn1(out)
+ out = self.relu(out)
+ out = self.conv2(out)
+ out = self.bn2(out)
+
+ out += residual
+ out = self.relu(out)
+ return out
+
+class PostRes(nn.Module):
+ def __init__(self, n_in, n_out, stride = 1):
+ super(PostRes, self).__init__()
+ self.conv1 = nn.Conv3d(n_in, n_out, kernel_size = 3, stride = stride, padding = 1)
+ self.bn1 = nn.BatchNorm3d(n_out)
+ self.relu = nn.ReLU(inplace = True)
+ self.conv2 = nn.Conv3d(n_out, n_out, kernel_size = 3, padding = 1)
+ self.bn2 = nn.BatchNorm3d(n_out)
+
+ if stride != 1 or n_out != n_in:
+ self.shortcut = nn.Sequential(
+ nn.Conv3d(n_in, n_out, kernel_size = 1, stride = stride),
+ nn.BatchNorm3d(n_out))
+ else:
+ self.shortcut = None
+
+ def forward(self, x):
+ residual = x
+ if self.shortcut is not None:
+ residual = self.shortcut(x)
+ out = self.conv1(x)
+ out = self.bn1(out)
+ out = self.relu(out)
+ out = self.conv2(out)
+ out = self.bn2(out)
+
+ out += residual
+ out = self.relu(out)
+ return out
+
+class Rec3(nn.Module):
+ def __init__(self, n0, n1, n2, n3, p = 0.0, integrate = True):
+ super(Rec3, self).__init__()
+
+ self.block01 = nn.Sequential(
+ nn.Conv3d(n0, n1, kernel_size = 3, stride = 2, padding = 1),
+ nn.BatchNorm3d(n1),
+ nn.ReLU(inplace = True),
+ nn.Conv3d(n1, n1, kernel_size = 3, padding = 1),
+ nn.BatchNorm3d(n1))
+
+ self.block11 = nn.Sequential(
+ nn.Conv3d(n1, n1, kernel_size = 3, padding = 1),
+ nn.BatchNorm3d(n1),
+ nn.ReLU(inplace = True),
+ nn.Conv3d(n1, n1, kernel_size = 3, padding = 1),
+ nn.BatchNorm3d(n1))
+
+ self.block21 = nn.Sequential(
+ nn.ConvTranspose3d(n2, n1, kernel_size = 2, stride = 2),
+ nn.BatchNorm3d(n1),
+ nn.ReLU(inplace = True),
+ nn.Conv3d(n1, n1, kernel_size = 3, padding = 1),
+ nn.BatchNorm3d(n1))
+
+ self.block12 = nn.Sequential(
+ nn.Conv3d(n1, n2, kernel_size = 3, stride = 2, padding = 1),
+ nn.BatchNorm3d(n2),
+ nn.ReLU(inplace = True),
+ nn.Conv3d(n2, n2, kernel_size = 3, padding = 1),
+ nn.BatchNorm3d(n2))
+
+ self.block22 = nn.Sequential(
+ nn.Conv3d(n2, n2, kernel_size = 3, padding = 1),
+ nn.BatchNorm3d(n2),
+ nn.ReLU(inplace = True),
+ nn.Conv3d(n2, n2, kernel_size = 3, padding = 1),
+ nn.BatchNorm3d(n2))
+
+ self.block32 = nn.Sequential(
+ nn.ConvTranspose3d(n3, n2, kernel_size = 2, stride = 2),
+ nn.BatchNorm3d(n2),
+ nn.ReLU(inplace = True),
+ nn.Conv3d(n2, n2, kernel_size = 3, padding = 1),
+ nn.BatchNorm3d(n2))
+
+ self.block23 = nn.Sequential(
+ nn.Conv3d(n2, n3, kernel_size = 3, stride = 2, padding = 1),
+ nn.BatchNorm3d(n3),
+ nn.ReLU(inplace = True),
+ nn.Conv3d(n3, n3, kernel_size = 3, padding = 1),
+ nn.BatchNorm3d(n3))
+
+ self.block33 = nn.Sequential(
+ nn.Conv3d(n3, n3, kernel_size = 3, padding = 1),
+ nn.BatchNorm3d(n3),
+ nn.ReLU(inplace = True),
+ nn.Conv3d(n3, n3, kernel_size = 3, padding = 1),
+ nn.BatchNorm3d(n3))
+
+ self.relu = nn.ReLU(inplace = True)
+ self.p = p
+ self.integrate = integrate
+
+ def forward(self, x0, x1, x2, x3):
+ if self.p > 0 and self.training:
+ coef = torch.bernoulli((1.0 - self.p) * torch.ones(8))
+ out1 = coef[0] * self.block01(x0) + coef[1] * self.block11(x1) + coef[2] * self.block21(x2)
+ out2 = coef[3] * self.block12(x1) + coef[4] * self.block22(x2) + coef[5] * self.block32(x3)
+ out3 = coef[6] * self.block23(x2) + coef[7] * self.block33(x3)
+ else:
+ out1 = (1 - self.p) * (self.block01(x0) + self.block11(x1) + self.block21(x2))
+ out2 = (1 - self.p) * (self.block12(x1) + self.block22(x2) + self.block32(x3))
+ out3 = (1 - self.p) * (self.block23(x2) + self.block33(x3))
+
+ if self.integrate:
+ out1 += x1
+ out2 += x2
+ out3 += x3
+
+ return x0, self.relu(out1), self.relu(out2), self.relu(out3)
+
+def hard_mining(neg_output, neg_labels, num_hard):
+ _, idcs = torch.topk(neg_output, min(num_hard, len(neg_output)))
+ neg_output = torch.index_select(neg_output, 0, idcs)
+ neg_labels = torch.index_select(neg_labels, 0, idcs)
+ return neg_output, neg_labels
+
+class Loss(nn.Module):
+ def __init__(self, num_hard = 0):
+ super(Loss, self).__init__()
+ self.sigmoid = nn.Sigmoid()
+ self.classify_loss = nn.BCELoss()
+ self.regress_loss = nn.SmoothL1Loss()
+ self.num_hard = num_hard
+
+ def forward(self, output, labels, train = True):
+ batch_size = labels.size(0)
+ output = output.view(-1, 5)
+ labels = labels.view(-1, 5)
+
+ pos_idcs = labels[:, 0] > 0.5
+ pos_idcs = pos_idcs.unsqueeze(1).expand(pos_idcs.size(0), 5)
+ pos_output = output[pos_idcs].view(-1, 5)
+ pos_labels = labels[pos_idcs].view(-1, 5)
+
+ neg_idcs = labels[:, 0] < -0.5
+ neg_output = output[:, 0][neg_idcs]
+ neg_labels = labels[:, 0][neg_idcs]
+
+ if self.num_hard > 0 and train:
+ neg_output, neg_labels = hard_mining(neg_output, neg_labels, self.num_hard * batch_size)
+ neg_prob = self.sigmoid(neg_output)
+
+ #classify_loss = self.classify_loss(
+ # torch.cat((pos_prob, neg_prob), 0),
+ # torch.cat((pos_labels[:, 0], neg_labels + 1), 0))
+ if len(pos_output)>0:
+ pos_prob = self.sigmoid(pos_output[:, 0])
+ pz, ph, pw, pd = pos_output[:, 1], pos_output[:, 2], pos_output[:, 3], pos_output[:, 4]
+ lz, lh, lw, ld = pos_labels[:, 1], pos_labels[:, 2], pos_labels[:, 3], pos_labels[:, 4]
+
+ regress_losses = [
+ self.regress_loss(pz, lz),
+ self.regress_loss(ph, lh),
+ self.regress_loss(pw, lw),
+ self.regress_loss(pd, ld)]
+ regress_losses_data = [l.data[0] for l in regress_losses]
+ classify_loss = 0.5 * self.classify_loss(
+ pos_prob, pos_labels[:, 0]) + 0.5 * self.classify_loss(
+ neg_prob, neg_labels + 1)
+ pos_correct = (pos_prob.data >= 0.5).sum()
+ pos_total = len(pos_prob)
+
+ else:
+ regress_losses = [0,0,0,0]
+ classify_loss = 0.5 * self.classify_loss(
+ neg_prob, neg_labels + 1)
+ pos_correct = 0
+ pos_total = 0
+ regress_losses_data = [0,0,0,0]
+ classify_loss_data = classify_loss.data[0]
+
+ loss = classify_loss
+ for regress_loss in regress_losses:
+ loss += regress_loss
+
+ neg_correct = (neg_prob.data < 0.5).sum()
+ neg_total = len(neg_prob)
+
+ return [loss, classify_loss_data] + regress_losses_data + [pos_correct, pos_total, neg_correct, neg_total]
+
+class GetPBB(object):
+ def __init__(self, config):
+ self.stride = config['stride']
+ self.anchors = np.asarray(config['anchors'])
+
+ def __call__(self, output,thresh = -3, ismask=False):
+ stride = self.stride
+ anchors = self.anchors
+ output = np.copy(output)
+ offset = (float(stride) - 1) / 2
+ output_size = output.shape
+ oz = np.arange(offset, offset + stride * (output_size[0] - 1) + 1, stride)
+ oh = np.arange(offset, offset + stride * (output_size[1] - 1) + 1, stride)
+ ow = np.arange(offset, offset + stride * (output_size[2] - 1) + 1, stride)
+
+ output[:, :, :, :, 1] = oz.reshape((-1, 1, 1, 1)) + output[:, :, :, :, 1] * anchors.reshape((1, 1, 1, -1))
+ output[:, :, :, :, 2] = oh.reshape((1, -1, 1, 1)) + output[:, :, :, :, 2] * anchors.reshape((1, 1, 1, -1))
+ output[:, :, :, :, 3] = ow.reshape((1, 1, -1, 1)) + output[:, :, :, :, 3] * anchors.reshape((1, 1, 1, -1))
+ output[:, :, :, :, 4] = np.exp(output[:, :, :, :, 4]) * anchors.reshape((1, 1, 1, -1))
+ mask = output[..., 0] > thresh
+ xx,yy,zz,aa = np.where(mask)
+
+ output = output[xx,yy,zz,aa]
+ if ismask:
+ return output,[xx,yy,zz,aa]
+ else:
+ return output
+
+ #output = output[output[:, 0] >= self.conf_th]
+ #bboxes = nms(output, self.nms_th)
+def nms(output, nms_th):
+ if len(output) == 0:
+ return output
+
+ output = output[np.argsort(-output[:, 0])]
+ bboxes = [output[0]]
+
+ for i in np.arange(1, len(output)):
+ bbox = output[i]
+ flag = 1
+ for j in range(len(bboxes)):
+ if iou(bbox[1:5], bboxes[j][1:5]) >= nms_th:
+ flag = -1
+ break
+ if flag == 1:
+ bboxes.append(bbox)
+
+ bboxes = np.asarray(bboxes, np.float32)
+ return bboxes
+
+def iou(box0, box1):
+
+ r0 = box0[3] / 2
+ s0 = box0[:3] - r0
+ e0 = box0[:3] + r0
+
+ r1 = box1[3] / 2
+ s1 = box1[:3] - r1
+ e1 = box1[:3] + r1
+
+ overlap = []
+ for i in range(len(s0)):
+ overlap.append(max(0, min(e0[i], e1[i]) - max(s0[i], s1[i])))
+
+ intersection = overlap[0] * overlap[1] * overlap[2]
+ union = box0[3] * box0[3] * box0[3] + box1[3] * box1[3] * box1[3] - intersection
+ return intersection / union
+
+def acc(pbb, lbb, conf_th, nms_th, detect_th):
+ pbb = pbb[pbb[:, 0] >= conf_th]
+ pbb = nms(pbb, nms_th)
+
+ tp = []
+ fp = []
+ fn = []
+ l_flag = np.zeros((len(lbb),), np.int32)
+ for p in pbb:
+ flag = 0
+ bestscore = 0
+ for i, l in enumerate(lbb):
+ score = iou(p[1:5], l)
+ if score>bestscore:
+ bestscore = score
+ besti = i
+ if bestscore > detect_th:
+ flag = 1
+ if l_flag[besti] == 0:
+ l_flag[besti] = 1
+ tp.append(np.concatenate([p,[bestscore]],0))
+ else:
+ fp.append(np.concatenate([p,[bestscore]],0))
+ if flag == 0:
+ fp.append(np.concatenate([p,[bestscore]],0))
+ for i,l in enumerate(lbb):
+ if l_flag[i]==0:
+ score = []
+ for p in pbb:
+ score.append(iou(p[1:5],l))
+ if len(score)!=0:
+ bestscore = np.max(score)
+ else:
+ bestscore = 0
+ if bestscore0:
+ fn = np.concatenate([fn,tp[fn_i,:5]])
+ else:
+ fn = fn
+ if len(tp_in_topk)>0:
+ tp = tp[tp_in_topk]
+ else:
+ tp = []
+ if len(fp_in_topk)>0:
+ fp = newallp[fp_in_topk]
+ else:
+ fp = []
+ return tp, fp , fn
diff --git a/training/classifier/main.py b/training/classifier/main.py
new file mode 100644
index 0000000..5e58a32
--- /dev/null
+++ b/training/classifier/main.py
@@ -0,0 +1,246 @@
+import argparse
+import os
+import time
+import numpy as np
+from importlib import import_module
+import shutil
+import sys
+from split_combine import SplitComb
+
+import torch
+from torch.nn import DataParallel
+from torch.backends import cudnn
+from torch.utils.data import DataLoader
+from torch import optim
+from torch.autograd import Variable
+
+from layers import acc
+from trainval_detector import *
+from trainval_classifier import *
+from data_detector import DataBowl3Detector
+from data_classifier import DataBowl3Classifier
+
+from utils import *
+
+parser = argparse.ArgumentParser(description='PyTorch DataBowl3 Detector')
+parser.add_argument('--model1', '-m1', metavar='MODEL', default='base',
+ help='model')
+parser.add_argument('--model2', '-m2', metavar='MODEL', default='base',
+ help='model')
+parser.add_argument('-j', '--workers', default=32, type=int, metavar='N',
+ help='number of data loading workers (default: 32)')
+parser.add_argument('--epochs', default=None, type=int, metavar='N',
+ help='number of total epochs to run')
+parser.add_argument('--start-epoch', default=0, type=int, metavar='N',
+ help='manual epoch number (useful on restarts)')
+parser.add_argument('-b', '--batch-size', default=16, type=int,
+ metavar='N', help='mini-batch size (default: 16)')
+parser.add_argument('-b2', '--batch-size2', default=3, type=int,
+ metavar='N', help='mini-batch size (default: 16)')
+parser.add_argument('--lr', '--learning-rate', default=None, type=float,
+ metavar='LR', help='initial learning rate')
+parser.add_argument('--momentum', default=0.9, type=float, metavar='M',
+ help='momentum')
+parser.add_argument('--weight-decay', '--wd', default=1e-4, type=float,
+ metavar='W', help='weight decay (default: 1e-4)')
+parser.add_argument('--save-freq', default='5', type=int, metavar='S',
+ help='save frequency')
+parser.add_argument('--resume', default='', type=str, metavar='PATH',
+ help='path to latest checkpoint (default: none)')
+parser.add_argument('--save-dir', default='', type=str, metavar='SAVE',
+ help='directory to save checkpoint (default: none)')
+parser.add_argument('--test1', default=0, type=int, metavar='TEST',
+ help='do detection test')
+parser.add_argument('--test2', default=0, type=int, metavar='TEST',
+ help='do classifier test')
+parser.add_argument('--test3', default=0, type=int, metavar='TEST',
+ help='do classifier test')
+parser.add_argument('--split', default=8, type=int, metavar='SPLIT',
+ help='In the test phase, split the image to 8 parts')
+parser.add_argument('--gpu', default='all', type=str, metavar='N',
+ help='use gpu')
+parser.add_argument('--n_test', default=8, type=int, metavar='N',
+ help='number of gpu for test')
+parser.add_argument('--debug', default=0, type=int, metavar='TEST',
+ help='debug mode')
+parser.add_argument('--freeze_batchnorm', default=0, type=int, metavar='TEST',
+ help='freeze the batchnorm when training')
+
+def main():
+ global args
+ args = parser.parse_args()
+
+
+ torch.manual_seed(0)
+
+
+ ##################################
+
+ nodmodel = import_module(args.model1)
+ config1, nod_net, loss, get_pbb = nodmodel.get_model()
+ args.lr_stage = config1['lr_stage']
+ args.lr_preset = config1['lr']
+
+
+ save_dir = args.save_dir
+
+
+ ##################################
+
+ casemodel = import_module(args.model2)
+
+ config2 = casemodel.config
+ args.lr_stage2 = config2['lr_stage']
+ args.lr_preset2 = config2['lr']
+ topk = config2['topk']
+ case_net = casemodel.CaseNet(topk = topk,nodulenet=nod_net)
+
+ args.miss_ratio = config2['miss_ratio']
+ args.miss_thresh = config2['miss_thresh']
+ if args.debug:
+ args.save_dir = 'debug'
+
+ ###################################
+
+
+
+
+
+
+ ################################
+ start_epoch = args.start_epoch
+ if args.resume:
+ checkpoint = torch.load(args.resume)
+ if start_epoch == 0:
+ start_epoch = checkpoint['epoch'] + 1
+ if not save_dir:
+ save_dir = checkpoint['save_dir']
+ else:
+ save_dir = os.path.join('results',save_dir)
+ case_net.load_state_dict(checkpoint['state_dict'])
+ else:
+ if start_epoch == 0:
+ start_epoch = 1
+ if not save_dir:
+ exp_id = time.strftime('%Y%m%d-%H%M%S', time.localtime())
+ save_dir = os.path.join('results', args.model1 + '-' + exp_id)
+ else:
+ save_dir = os.path.join('results',save_dir)
+ if args.epochs == None:
+ end_epoch = args.lr_stage2[-1]
+ else:
+ end_epoch = args.epochs
+ ################################
+ if not os.path.exists(save_dir):
+ os.makedirs(save_dir)
+ logfile = os.path.join(save_dir,'log')
+ if args.test1!=1 and args.test2!=1 :
+ sys.stdout = Logger(logfile)
+ pyfiles = [f for f in os.listdir('./') if f.endswith('.py')]
+ for f in pyfiles:
+ shutil.copy(f,os.path.join(save_dir,f))
+ ################################
+ torch.cuda.set_device(0)
+ #nod_net = nod_net.cuda()
+ case_net = case_net.cuda()
+ loss = loss.cuda()
+ cudnn.benchmark = True
+ if not args.debug:
+ case_net = DataParallel(case_net)
+ nod_net = DataParallel(nod_net)
+ ################################
+
+
+ if args.test1 == 1:
+ testsplit = np.load('full.npy')
+ dataset = DataBowl3Classifier(testsplit, config2, phase = 'test')
+ predlist = test_casenet(case_net,dataset).T
+ anstable = np.concatenate([[testsplit],predlist],0).T
+ df = pandas.DataFrame(anstable)
+ df.columns={'id','cancer'}
+ df.to_csv('allstage1.csv',index=False)
+ return
+
+ if args.test2 ==1:
+
+ testsplit = np.load('test.npy')
+ dataset = DataBowl3Classifier(testsplit, config2, phase = 'test')
+ predlist = test_casenet(case_net,dataset).T
+ anstable = np.concatenate([[testsplit],predlist],0).T
+ df = pandas.DataFrame(anstable)
+ df.columns={'id','cancer'}
+ df.to_csv('quick',index=False)
+ return
+ if args.test3 == 1:
+ testsplit3 = np.load('stage2.npy')
+ dataset = DataBowl3Classifier(testsplit3,config2,phase = 'test')
+ predlist = test_casenet(case_net,dataset).T
+ anstable = np.concatenate([[testsplit3],predlist],0).T
+ df = pandas.DataFrame(anstable)
+ df.columns={'id','cancer'}
+ df.to_csv('stage2_ans.csv',index=False)
+ return
+ print(save_dir)
+ print(args.save_freq)
+ trainsplit = np.load('kaggleluna_full.npy')
+ valsplit = np.load('valsplit.npy')
+ testsplit = np.load('test.npy')
+
+ dataset = DataBowl3Detector(trainsplit,config1,phase = 'train')
+ train_loader_nod = DataLoader(dataset,batch_size = args.batch_size,
+ shuffle = True,num_workers = args.workers,pin_memory=True)
+
+ dataset = DataBowl3Detector(valsplit,config1,phase = 'val')
+ val_loader_nod = DataLoader(dataset,batch_size = args.batch_size,
+ shuffle = False,num_workers = args.workers,pin_memory=True)
+
+ optimizer = torch.optim.SGD(nod_net.parameters(),
+ args.lr,momentum = 0.9,weight_decay = args.weight_decay)
+
+ trainsplit = np.load('full.npy')
+ dataset = DataBowl3Classifier(trainsplit,config2,phase = 'train')
+ train_loader_case = DataLoader(dataset,batch_size = args.batch_size2,
+ shuffle = True,num_workers = args.workers,pin_memory=True)
+
+ dataset = DataBowl3Classifier(valsplit,config2,phase = 'val')
+ val_loader_case = DataLoader(dataset,batch_size = max([args.batch_size2,1]),
+ shuffle = False,num_workers = args.workers,pin_memory=True)
+
+ dataset = DataBowl3Classifier(trainsplit,config2,phase = 'val')
+ all_loader_case = DataLoader(dataset,batch_size = max([args.batch_size2,1]),
+ shuffle = False,num_workers = args.workers,pin_memory=True)
+
+ optimizer2 = torch.optim.SGD(case_net.parameters(),
+ args.lr,momentum = 0.9,weight_decay = args.weight_decay)
+
+ for epoch in range(start_epoch, end_epoch + 1):
+ if epoch ==start_epoch:
+ lr = args.lr
+ debug = args.debug
+ args.lr = 0.0
+ args.debug = True
+ train_casenet(epoch,case_net,train_loader_case,optimizer2,args)
+ args.lr = lr
+ args.debug = debug
+ if epochconfig2['startepoch']:
+ train_casenet(epoch,case_net,train_loader_case,optimizer2,args)
+ val_casenet(epoch,case_net,val_loader_case,args)
+ val_casenet(epoch,case_net,all_loader_case,args)
+
+ if epoch % args.save_freq == 0:
+ state_dict = case_net.module.state_dict()
+ for key in state_dict.keys():
+ state_dict[key] = state_dict[key].cpu()
+
+ torch.save({
+ 'epoch': epoch,
+ 'save_dir': save_dir,
+ 'state_dict': state_dict,
+ 'args': args},
+ os.path.join(save_dir, '%03d.ckpt' % epoch))
+if __name__ == '__main__':
+ main()
+
diff --git a/training/classifier/net_classifier_3.py b/training/classifier/net_classifier_3.py
new file mode 100644
index 0000000..ae30a4e
--- /dev/null
+++ b/training/classifier/net_classifier_3.py
@@ -0,0 +1,83 @@
+import torch
+from torch import nn
+from layers import *
+from torch.nn import DataParallel
+from torch.backends import cudnn
+from torch.utils.data import DataLoader
+from torch import optim
+from torch.autograd import Variable
+from torch.utils.data import Dataset
+from scipy.ndimage.interpolation import rotate
+import numpy as np
+import os
+import sys
+sys.path.append('../')
+from config_training import config as config_training
+
+config = {}
+config['topk'] = 5
+config['resample'] = None
+config['datadir'] = config_training['preprocess_result_path']
+config['preload_train'] = True
+config['bboxpath'] = config_training['bbox_path']
+config['labelfile'] = './full_label.csv'
+config['preload_val'] = True
+
+config['padmask'] = False
+
+config['crop_size'] = [96,96,96]
+config['scaleLim'] = [0.85,1.15]
+config['radiusLim'] = [6,100]
+config['jitter_range'] = 0.15
+config['isScale'] = True
+
+config['random_sample'] = True
+config['T'] = 1
+config['topk'] = 5
+config['stride'] = 4
+config['augtype'] = {'flip':True,'swap':False,'rotate':False,'scale':False}
+
+config['detect_th'] = 0.05
+config['conf_th'] = -1
+config['nms_th'] = 0.05
+config['filling_value'] = 160
+
+config['startepoch'] = 20
+config['lr_stage'] = np.array([50,100,140,160])
+config['lr'] = [0.01,0.001,0.0001,0.00001]
+config['miss_ratio'] = 1
+config['miss_thresh'] = 0.03
+
+class CaseNet(nn.Module):
+ def __init__(self,topk,nodulenet):
+ super(CaseNet,self).__init__()
+ self.NoduleNet = nodulenet
+ self.fc1 = nn.Linear(128,64)
+ self.fc2 = nn.Linear(64,1)
+ self.pool = nn.MaxPool3d(kernel_size=2)
+ self.dropout = nn.Dropout(0.5)
+ self.baseline = nn.Parameter(torch.Tensor([-30.0]).float())
+ self.Relu = nn.ReLU()
+ def forward(self,xlist,coordlist):
+# xlist: n x k x 1x 96 x 96 x 96
+# coordlist: n x k x 3 x 24 x 24 x 24
+ xsize = xlist.size()
+ corrdsize = coordlist.size()
+ xlist = xlist.view(-1,xsize[2],xsize[3],xsize[4],xsize[5])
+ coordlist = coordlist.view(-1,corrdsize[2],corrdsize[3],corrdsize[4],corrdsize[5])
+
+ noduleFeat,nodulePred = self.NoduleNet(xlist,coordlist)
+ nodulePred = nodulePred.contiguous().view(corrdsize[0],corrdsize[1],-1)
+
+ featshape = noduleFeat.size()#nk x 128 x 24 x 24 x24
+ centerFeat = self.pool(noduleFeat[:,:,featshape[2]/2-1:featshape[2]/2+1,
+ featshape[3]/2-1:featshape[3]/2+1,
+ featshape[4]/2-1:featshape[4]/2+1])
+ centerFeat = centerFeat[:,:,0,0,0]
+ out = self.dropout(centerFeat)
+ out = self.Relu(self.fc1(out))
+ out = torch.sigmoid(self.fc2(out))
+ out = out.view(xsize[0],xsize[1])
+ base_prob = torch.sigmoid(self.baseline)
+ casePred = 1-torch.prod(1-out,dim=1)*(1-base_prob.expand(out.size()[0]))
+ return nodulePred,casePred,out
diff --git a/training/classifier/net_classifier_4.py b/training/classifier/net_classifier_4.py
new file mode 100644
index 0000000..953ba21
--- /dev/null
+++ b/training/classifier/net_classifier_4.py
@@ -0,0 +1,80 @@
+import torch
+from torch import nn
+from layers import *
+from torch.nn import DataParallel
+from torch.backends import cudnn
+from torch.utils.data import DataLoader
+from torch import optim
+from torch.autograd import Variable
+from torch.utils.data import Dataset
+from scipy.ndimage.interpolation import rotate
+import numpy as np
+import os
+
+config = {}
+config['topk'] = 5
+config['resample'] = None
+config['datadir'] = '/work/DataBowl3/stage1/preprocess_1_3/'
+config['preload_train'] = True
+config['bboxpath'] = '../cpliangming/results/res18_mylabel/bbox/'
+config['labelfile'] = 'full_label.csv'
+config['preload_val'] = True
+
+config['padmask'] = False
+
+config['crop_size'] = [96,96,96]
+config['scaleLim'] = [0.85,1.15]
+config['radiusLim'] = [6,100]
+config['jitter_range'] = 0.15
+config['isScale'] = True
+
+config['random_sample'] = True
+config['T'] = 1
+config['topk'] = 5
+config['stride'] = 4
+config['augtype'] = {'flip':True,'swap':True,'rotate':True,'scale':True}
+
+config['detect_th'] = 0.05
+config['conf_th'] = -1
+config['nms_th'] = 0.05
+config['filling_value'] = 160
+
+config['startepoch'] = 20
+config['lr_stage'] = np.array([50,100,140,160,180])
+config['lr'] = [0.01,0.001,0.0001,0.00001,0.000001]
+config['miss_ratio'] = 1
+config['miss_thresh'] = 0.03
+
+class CaseNet(nn.Module):
+ def __init__(self,topk,nodulenet):
+ super(CaseNet,self).__init__()
+ self.NoduleNet = nodulenet
+ self.fc1 = nn.Linear(128,64)
+ self.fc2 = nn.Linear(64,1)
+ self.pool = nn.MaxPool3d(kernel_size=2)
+ self.dropout = nn.Dropout(0.5)
+ self.baseline = nn.Parameter(torch.Tensor([-30.0]).float())
+ self.Relu = nn.ReLU()
+ def forward(self,xlist,coordlist):
+# xlist: n x k x 1x 96 x 96 x 96
+# coordlist: n x k x 3 x 24 x 24 x 24
+ xsize = xlist.size()
+ corrdsize = coordlist.size()
+ xlist = xlist.view(-1,xsize[2],xsize[3],xsize[4],xsize[5])
+ coordlist = coordlist.view(-1,corrdsize[2],corrdsize[3],corrdsize[4],corrdsize[5])
+
+ noduleFeat,nodulePred = self.NoduleNet(xlist,coordlist)
+ nodulePred = nodulePred.contiguous().view(corrdsize[0],corrdsize[1],-1)
+
+ featshape = noduleFeat.size()#nk x 128 x 24 x 24 x24
+ centerFeat = self.pool(noduleFeat[:,:,featshape[2]/2-1:featshape[2]/2+1,
+ featshape[3]/2-1:featshape[3]/2+1,
+ featshape[4]/2-1:featshape[4]/2+1])
+ centerFeat = centerFeat[:,:,0,0,0]
+ out = self.dropout(centerFeat)
+ out = self.Relu(self.fc1(out))
+ out = torch.sigmoid(self.fc2(out))
+ out = out.view(xsize[0],xsize[1])
+ base_prob = torch.sigmoid(self.baseline)
+ casePred = 1-torch.prod(1-out,dim=1)*(1-base_prob.expand(out.size()[0]))
+ return nodulePred,casePred,out
diff --git a/training/classifier/net_detector_3.py b/training/classifier/net_detector_3.py
new file mode 100644
index 0000000..2277ded
--- /dev/null
+++ b/training/classifier/net_detector_3.py
@@ -0,0 +1,136 @@
+import torch
+from torch import nn
+from layers import *
+import sys
+sys.path.append('../')
+from config_training import config as config_training
+
+
+config = {}
+config['anchors'] = [ 10.0, 30.0, 60.]
+config['chanel'] = 1
+config['crop_size'] = [128, 128, 128]
+config['stride'] = 4
+config['datadir'] = config_training['preprocess_result_path']
+
+config['max_stride'] = 16
+config['num_neg'] = 800
+config['th_neg'] = 0.02
+config['th_pos_train'] = 0.5
+config['th_pos_val'] = 1
+config['num_hard'] = 2
+config['bound_size'] = 12
+config['reso'] = 1
+config['sizelim'] = 6. #mm
+config['sizelim2'] = 30
+config['sizelim3'] = 40
+config['aug_scale'] = True
+config['r_rand_crop'] = 0.3
+config['pad_value'] = 170
+config['augtype'] = {'flip':True,'swap':False,'scale':True,'rotate':False}
+config['blacklist'] = ['868b024d9fa388b7ddab12ec1c06af38','990fbe3f0a1b53878669967b9afd1441','adc3bbc63d40f8761c59be10f1e504c3']
+
+
+config['lr_stage'] = np.array([50,100,140,160])
+config['lr'] = [0.01,0.001,0.0001,0.00001]
+
+#config['blacklist'] = ['868b024d9fa388b7ddab12ec1c06af38','d92998a73d4654a442e6d6ba15bbb827','990fbe3f0a1b53878669967b9afd1441','820245d8b211808bd18e78ff5be16fdb','adc3bbc63d40f8761c59be10f1e504c3',
+# '417','077','188','876','057','087','130','468']
+
+class Net(nn.Module):
+ def __init__(self):
+ super(Net, self).__init__()
+ # The first few layers consumes the most memory, so use simple convolution to save memory.
+ # Call these layers preBlock, i.e., before the residual blocks of later layers.
+ self.preBlock = nn.Sequential(
+ nn.Conv3d(1, 24, kernel_size = 3, padding = 1),
+ nn.BatchNorm3d(24),
+ nn.ReLU(inplace = True),
+ nn.Conv3d(24, 24, kernel_size = 3, padding = 1),
+ nn.BatchNorm3d(24),
+ nn.ReLU(inplace = True))
+
+ # 3 poolings, each pooling downsamples the feature map by a factor 2.
+ # 3 groups of blocks. The first block of each group has one pooling.
+ num_blocks_forw = [2,2,3,3]
+ num_blocks_back = [3,3]
+ self.featureNum_forw = [24,32,64,64,64]
+ self.featureNum_back = [128,64,64]
+ for i in range(len(num_blocks_forw)):
+ blocks = []
+ for j in range(num_blocks_forw[i]):
+ if j == 0:
+ blocks.append(PostRes(self.featureNum_forw[i], self.featureNum_forw[i+1]))
+ else:
+ blocks.append(PostRes(self.featureNum_forw[i+1], self.featureNum_forw[i+1]))
+ setattr(self, 'forw' + str(i + 1), nn.Sequential(*blocks))
+
+
+ for i in range(len(num_blocks_back)):
+ blocks = []
+ for j in range(num_blocks_back[i]):
+ if j == 0:
+ if i==0:
+ addition = 3
+ else:
+ addition = 0
+ blocks.append(PostRes(self.featureNum_back[i+1]+self.featureNum_forw[i+2]+addition, self.featureNum_back[i]))
+ else:
+ blocks.append(PostRes(self.featureNum_back[i], self.featureNum_back[i]))
+ setattr(self, 'back' + str(i + 2), nn.Sequential(*blocks))
+
+ self.maxpool1 = nn.MaxPool3d(kernel_size=2,stride=2,return_indices =True)
+ self.maxpool2 = nn.MaxPool3d(kernel_size=2,stride=2,return_indices =True)
+ self.maxpool3 = nn.MaxPool3d(kernel_size=2,stride=2,return_indices =True)
+ self.maxpool4 = nn.MaxPool3d(kernel_size=2,stride=2,return_indices =True)
+ self.unmaxpool1 = nn.MaxUnpool3d(kernel_size=2,stride=2)
+ self.unmaxpool2 = nn.MaxUnpool3d(kernel_size=2,stride=2)
+
+ self.path1 = nn.Sequential(
+ nn.ConvTranspose3d(64, 64, kernel_size = 2, stride = 2),
+ nn.BatchNorm3d(64),
+ nn.ReLU(inplace = True))
+ self.path2 = nn.Sequential(
+ nn.ConvTranspose3d(64, 64, kernel_size = 2, stride = 2),
+ nn.BatchNorm3d(64),
+ nn.ReLU(inplace = True))
+ self.drop = nn.Dropout3d(p = 0.2, inplace = False)
+ self.output = nn.Sequential(nn.Conv3d(self.featureNum_back[0], 64, kernel_size = 1),
+ nn.ReLU(),
+ #nn.Dropout3d(p = 0.3),
+ nn.Conv3d(64, 5 * len(config['anchors']), kernel_size = 1))
+
+ def forward(self, x, coord):
+ #x = (x-128.)/128.
+ out = self.preBlock(x)#16
+ out_pool,indices0 = self.maxpool1(out)
+ out1 = self.forw1(out_pool)#32
+ out1_pool,indices1 = self.maxpool2(out1)
+ out2 = self.forw2(out1_pool)#64
+ #out2 = self.drop(out2)
+ out2_pool,indices2 = self.maxpool3(out2)
+ out3 = self.forw3(out2_pool)#96
+ out3_pool,indices3 = self.maxpool4(out3)
+ out4 = self.forw4(out3_pool)#96
+ #out4 = self.drop(out4)
+
+ rev3 = self.path1(out4)
+ comb3 = self.back3(torch.cat((rev3, out3), 1))#96+96
+ #comb3 = self.drop(comb3)
+ rev2 = self.path2(comb3)
+
+ feat = self.back2(torch.cat((rev2, out2,coord), 1))#64+64
+ comb2 = self.drop(feat)
+ out = self.output(comb2)
+ size = out.size()
+ out = out.view(out.size(0), out.size(1), -1)
+ #out = out.transpose(1, 4).transpose(1, 2).transpose(2, 3).contiguous()
+ out = out.transpose(1, 2).contiguous().view(size[0], size[2], size[3], size[4], len(config['anchors']), 5)
+ #out = out.view(-1, 5)
+ return feat,out
+
+def get_model():
+ net = Net()
+ loss = Loss(config['num_hard'])
+ get_pbb = GetPBB(config)
+ return config, net, loss, get_pbb
diff --git a/training/classifier/newtrain.npy b/training/classifier/newtrain.npy
new file mode 100644
index 0000000..021977e
Binary files /dev/null and b/training/classifier/newtrain.npy differ
diff --git a/training/classifier/results/.gitignore b/training/classifier/results/.gitignore
new file mode 100644
index 0000000..76bedae
--- /dev/null
+++ b/training/classifier/results/.gitignore
@@ -0,0 +1,5 @@
+# Ignore everything in this directory
+*
+# Except this file
+!.gitignore
+
diff --git a/training/classifier/split_combine.py b/training/classifier/split_combine.py
new file mode 100644
index 0000000..2e399a9
--- /dev/null
+++ b/training/classifier/split_combine.py
@@ -0,0 +1,99 @@
+import torch
+import numpy as np
+class SplitComb():
+ def __init__(self,side_len,max_stride,stride,margin):
+ self.side_len = side_len
+ self.max_stride = max_stride
+ self.stride = stride
+ self.margin = margin
+
+ def split(self, data, side_len = None, max_stride = None, margin = None):
+ if side_len==None:
+ side_len = self.side_len
+ if max_stride == None:
+ max_stride = self.max_stride
+ if margin == None:
+ margin = self.margin
+
+ assert(side_len > margin)
+ assert(side_len % max_stride == 0)
+ assert(margin % max_stride == 0)
+
+ splits = []
+ _, z, h, w = data.shape
+
+ nz = int(np.ceil(float(z) / side_len))
+ nh = int(np.ceil(float(h) / side_len))
+ nw = int(np.ceil(float(w) / side_len))
+
+ nzhw = [nz,nh,nw]
+ self.nzhw = nzhw
+
+ pad = [ [0, 0],
+ [margin, nz * side_len - z + margin],
+ [margin, nh * side_len - h + margin],
+ [margin, nw * side_len - w + margin]]
+ data = np.pad(data, pad, 'constant')
+
+ for iz in range(nz):
+ for ih in range(nh):
+ for iw in range(nw):
+ sz = iz * side_len
+ ez = (iz + 1) * side_len + 2 * margin
+ sh = ih * side_len
+ eh = (ih + 1) * side_len + 2 * margin
+ sw = iw * side_len
+ ew = (iw + 1) * side_len + 2 * margin
+
+ split = data[np.newaxis, :, sz:ez, sh:eh, sw:ew]
+ splits.append(split)
+
+ splits = np.concatenate(splits, 0)
+ return splits,nzhw
+
+ def combine(self, output, nzhw = None, side_len=None, stride=None, margin=None):
+
+ if side_len==None:
+ side_len = self.side_len
+ if stride == None:
+ stride = self.stride
+ if margin == None:
+ margin = self.margin
+ if nzhw==None:
+ nz = self.nz
+ nh = self.nh
+ nw = self.nw
+ else:
+ nz,nh,nw = nzhw
+ assert(side_len % stride == 0)
+ assert(margin % stride == 0)
+ side_len /= stride
+ margin /= stride
+
+ splits = []
+ for i in range(len(output)):
+ splits.append(output[i])
+
+ output = -1000000 * np.ones((
+ nz * side_len,
+ nh * side_len,
+ nw * side_len,
+ splits[0].shape[3],
+ splits[0].shape[4]), np.float32)
+
+ idx = 0
+ for iz in range(nz):
+ for ih in range(nh):
+ for iw in range(nw):
+ sz = iz * side_len
+ ez = (iz + 1) * side_len
+ sh = ih * side_len
+ eh = (ih + 1) * side_len
+ sw = iw * side_len
+ ew = (iw + 1) * side_len
+
+ split = splits[idx][margin:margin + side_len, margin:margin + side_len, margin:margin + side_len]
+ output[sz:ez, sh:eh, sw:ew] = split
+ idx += 1
+
+ return output
diff --git a/training/classifier/stage2.npy b/training/classifier/stage2.npy
new file mode 100644
index 0000000..4038e17
Binary files /dev/null and b/training/classifier/stage2.npy differ
diff --git a/training/classifier/test.npy b/training/classifier/test.npy
new file mode 100644
index 0000000..53d21d0
Binary files /dev/null and b/training/classifier/test.npy differ
diff --git a/training/classifier/trainval_classifier.py b/training/classifier/trainval_classifier.py
new file mode 100644
index 0000000..88951eb
--- /dev/null
+++ b/training/classifier/trainval_classifier.py
@@ -0,0 +1,161 @@
+import numpy as np
+import os
+import time
+import random
+import warnings
+
+import torch
+from torch import nn
+from torch import optim
+from torch.autograd import Variable
+from torch.nn.functional import cross_entropy,sigmoid,binary_cross_entropy
+from torch.utils.data import DataLoader
+
+def get_lr(epoch,args):
+ assert epoch<=args.lr_stage2[-1]
+ if args.lr==None:
+ lrstage = np.sum(epoch>args.lr_stage2)
+ lr = args.lr_preset2[lrstage]
+ else:
+ lr = args.lr
+ return lr
+
+def train_casenet(epoch,model,data_loader,optimizer,args):
+ model.train()
+ if args.freeze_batchnorm:
+ for m in model.modules():
+ if isinstance(m, nn.BatchNorm3d):
+ m.eval()
+
+ starttime = time.time()
+ lr = get_lr(epoch,args)
+ for param_group in optimizer.param_groups:
+ param_group['lr'] = lr
+
+ loss1Hist = []
+ loss2Hist = []
+ missHist = []
+ lossHist = []
+ accHist = []
+ lenHist = []
+ tpn = 0
+ fpn = 0
+ fnn = 0
+# weight = torch.from_numpy(np.ones_like(y).float().cuda()
+ for i,(x,coord,isnod,y) in enumerate(data_loader):
+ if args.debug:
+ if i >4:
+ break
+ coord = Variable(coord).cuda()
+ x = Variable(x).cuda()
+ xsize = x.size()
+ isnod = Variable(isnod).float().cuda()
+ ydata = y.numpy()[:,0]
+ y = Variable(y).float().cuda()
+# weight = 3*torch.ones(y.size()).float().cuda()
+ optimizer.zero_grad()
+ nodulePred,casePred,casePred_each = model(x,coord)
+ loss2 = binary_cross_entropy(casePred,y[:,0])
+ missMask = (casePred_each0.5
+ tpn += np.sum(1==pred[ydata==1])
+ fpn += np.sum(1==pred[ydata==0])
+ fnn += np.sum(0==pred[ydata==1])
+ acc = np.mean(ydata==pred)
+ accHist.append(acc)
+
+ endtime = time.time()
+ lenHist = np.array(lenHist)
+ loss2Hist = np.array(loss2Hist)
+ lossHist = np.array(lossHist)
+ accHist = np.array(accHist)
+
+ mean_loss2 = np.sum(loss2Hist*lenHist)/np.sum(lenHist)
+ mean_missloss = np.sum(missHist*lenHist)/np.sum(lenHist)
+ mean_acc = np.sum(accHist*lenHist)/np.sum(lenHist)
+ print('Train, epoch %d, loss2 %.4f, miss loss %.4f, acc %.4f, tpn %d, fpn %d, fnn %d, time %3.2f, lr % .5f '
+ %(epoch,mean_loss2,mean_missloss,mean_acc,tpn,fpn, fnn, endtime-starttime,lr))
+
+def val_casenet(epoch,model,data_loader,args):
+ model.eval()
+ starttime = time.time()
+ loss1Hist = []
+ loss2Hist = []
+ lossHist = []
+ missHist = []
+ accHist = []
+ lenHist = []
+ tpn = 0
+ fpn = 0
+ fnn = 0
+
+ for i,(x,coord,isnod,y) in enumerate(data_loader):
+
+ coord = Variable(coord,volatile=True).cuda()
+ x = Variable(x,volatile=True).cuda()
+ xsize = x.size()
+ ydata = y.numpy()[:,0]
+ y = Variable(y).float().cuda()
+ isnod = Variable(isnod).float().cuda()
+
+ nodulePred,casePred,casePred_each = model(x,coord)
+
+ loss2 = binary_cross_entropy(casePred,y[:,0])
+ missMask = (casePred_each0.5
+ tpn += np.sum(1==pred[ydata==1])
+ fpn += np.sum(1==pred[ydata==0])
+ fnn += np.sum(0==pred[ydata==1])
+ acc = np.mean(ydata==pred)
+ accHist.append(acc)
+ endtime = time.time()
+ lenHist = np.array(lenHist)
+ loss2Hist = np.array(loss2Hist)
+ accHist = np.array(accHist)
+ mean_loss2 = np.sum(loss2Hist*lenHist)/np.sum(lenHist)
+ mean_missloss = np.sum(missHist*lenHist)/np.sum(lenHist)
+ mean_acc = np.sum(accHist*lenHist)/np.sum(lenHist)
+ print('Valid, epoch %d, loss2 %.4f, miss loss %.4f, acc %.4f, tpn %d, fpn %d, fnn %d, time %3.2f'
+ %(epoch,mean_loss2,mean_missloss,mean_acc,tpn,fpn, fnn, endtime-starttime))
+
+
+def test_casenet(model,testset):
+ data_loader = DataLoader(
+ testset,
+ batch_size = 4,
+ shuffle = False,
+ num_workers = 32,
+ pin_memory=True)
+ #model = model.cuda()
+ model.eval()
+ predlist = []
+
+ # weight = torch.from_numpy(np.ones_like(y).float().cuda()
+ for i,(x,coord) in enumerate(data_loader):
+
+ coord = Variable(coord).cuda()
+ x = Variable(x).cuda()
+ nodulePred,casePred,_ = model(x,coord)
+ predlist.append(casePred.data.cpu().numpy())
+ #print([i,data_loader.dataset.split[i,1],casePred.data.cpu().numpy()])
+ predlist = np.concatenate(predlist)
+ return predlist
diff --git a/training/classifier/trainval_detector.py b/training/classifier/trainval_detector.py
new file mode 100644
index 0000000..6e02b13
--- /dev/null
+++ b/training/classifier/trainval_detector.py
@@ -0,0 +1,157 @@
+import os
+import time
+import numpy as np
+
+import torch
+from torch import nn
+from torch.nn import DataParallel
+from torch.backends import cudnn
+from torch.utils.data import DataLoader
+from torch import optim
+from torch.autograd import Variable
+
+from layers import acc
+
+def get_lr(epoch,args):
+ assert epoch<=args.lr_stage[-1]
+ if args.lr==None:
+ lrstage = np.sum(epoch>args.lr_stage)
+ lr = args.lr_preset[lrstage]
+ else:
+ lr = args.lr
+ return lr
+
+def train_nodulenet(data_loader, net, loss, epoch, optimizer, args):
+ start_time = time.time()
+ net.train()
+ if args.freeze_batchnorm:
+ for m in net.modules():
+ if isinstance(m, nn.BatchNorm3d):
+ m.eval()
+
+ lr = get_lr(epoch,args)
+ for param_group in optimizer.param_groups:
+ param_group['lr'] = lr
+
+ metrics = []
+ for i, (data, target, coord) in enumerate(data_loader):
+ if args.debug:
+ if i >4:
+ break
+ data = Variable(data.cuda(async = True))
+ target = Variable(target.cuda(async = True))
+ coord = Variable(coord.cuda(async = True))
+
+ _,output = net(data, coord)
+ loss_output = loss(output, target)
+ optimizer.zero_grad()
+ loss_output[0].backward()
+ #torch.nn.utils.clip_grad_norm(net.parameters(), 1)
+ optimizer.step()
+
+ loss_output[0] = loss_output[0].data[0]
+ metrics.append(loss_output)
+
+ end_time = time.time()
+
+ metrics = np.asarray(metrics, np.float32)
+ print('Epoch %03d (lr %.5f)' % (epoch, lr))
+ print('Train: tpr %3.2f, tnr %3.2f, total pos %d, total neg %d, time %3.2f' % (
+ 100.0 * np.sum(metrics[:, 6]) / np.sum(metrics[:, 7]),
+ 100.0 * np.sum(metrics[:, 8]) / np.sum(metrics[:, 9]),
+ np.sum(metrics[:, 7]),
+ np.sum(metrics[:, 9]),
+ end_time - start_time))
+ print('loss %2.4f, classify loss %2.4f, regress loss %2.4f, %2.4f, %2.4f, %2.4f' % (
+ np.mean(metrics[:, 0]),
+ np.mean(metrics[:, 1]),
+ np.mean(metrics[:, 2]),
+ np.mean(metrics[:, 3]),
+ np.mean(metrics[:, 4]),
+ np.mean(metrics[:, 5])))
+ print
+
+def validate_nodulenet(data_loader, net, loss):
+ start_time = time.time()
+
+ net.eval()
+
+ metrics = []
+ for i, (data, target, coord) in enumerate(data_loader):
+ data = Variable(data.cuda(async = True), volatile = True)
+ target = Variable(target.cuda(async = True), volatile = True)
+ coord = Variable(coord.cuda(async = True), volatile = True)
+
+ _,output = net(data, coord)
+ loss_output = loss(output, target, train = False)
+
+ loss_output[0] = loss_output[0].data[0]
+ metrics.append(loss_output)
+ end_time = time.time()
+
+ metrics = np.asarray(metrics, np.float32)
+ print('Validation: tpr %3.2f, tnr %3.8f, total pos %d, total neg %d, time %3.2f' % (
+ 100.0 * np.sum(metrics[:, 6]) / np.sum(metrics[:, 7]),
+ 100.0 * np.sum(metrics[:, 8]) / np.sum(metrics[:, 9]),
+ np.sum(metrics[:, 7]),
+ np.sum(metrics[:, 9]),
+ end_time - start_time))
+ print('loss %2.4f, classify loss %2.4f, regress loss %2.4f, %2.4f, %2.4f, %2.4f' % (
+ np.mean(metrics[:, 0]),
+ np.mean(metrics[:, 1]),
+ np.mean(metrics[:, 2]),
+ np.mean(metrics[:, 3]),
+ np.mean(metrics[:, 4]),
+ np.mean(metrics[:, 5])))
+ print
+ print
+
+def test_nodulenet(data_loader, net, get_pbb, save_dir, config, n_per_run):
+ start_time = time.time()
+ save_dir = os.path.join(save_dir,'bbox')
+ if not os.path.exists(save_dir):
+ os.makedirs(save_dir)
+ net.eval()
+ namelist = []
+ split_comber = data_loader.dataset.split_comber
+ for i_name, (data, target, coord, nzhw) in enumerate(data_loader):
+ s = time.time()
+ target = [np.asarray(t, np.float32) for t in target]
+ lbb = target[0]
+ nzhw = nzhw[0]
+ name = data_loader.dataset.filenames[i_name].split('-')[0].split('/')[-1]
+ data = data[0][0]
+ coord = coord[0][0]
+ isfeat = False
+ if 'output_feature' in config:
+ if config['output_feature']:
+ isfeat = True
+ print(data.size())
+ splitlist = range(0,len(data)+1,n_per_run)
+ if splitlist[-1]!=len(data):
+ splitlist.append(len(data))
+ outputlist = []
+ featurelist = []
+
+ for i in range(len(splitlist)-1):
+ input = Variable(data[splitlist[i]:splitlist[i+1]], volatile = True).cuda()
+ inputcoord = Variable(coord[splitlist[i]:splitlist[i+1]], volatile = True).cuda()
+ _,output = net(input,inputcoord)
+ outputlist.append(output.data.cpu().numpy())
+ output = np.concatenate(outputlist,0)
+ output = split_comber.combine(output,nzhw=nzhw)
+ thresh = -3
+ pbb,mask = get_pbb(output,thresh,ismask=True)
+ #tp,fp,fn,_ = acc(pbb,lbb,0,0.1,0.1)
+ #print([len(tp),len(fp),len(fn)])
+ print([i_name,name])
+ e = time.time()
+ np.save(os.path.join(save_dir, name+'_pbb.npy'), pbb)
+ np.save(os.path.join(save_dir, name+'_lbb.npy'), lbb)
+ np.save(os.path.join(save_dir, 'namelist.npy'), namelist)
+ end_time = time.time()
+
+
+ print('elapsed time is %3.2f seconds' % (end_time - start_time))
+ print
+ print
diff --git a/training/classifier/utils.py b/training/classifier/utils.py
new file mode 100644
index 0000000..8743c82
--- /dev/null
+++ b/training/classifier/utils.py
@@ -0,0 +1,308 @@
+import sys
+import os
+import numpy as np
+import torch
+def getFreeId():
+ import pynvml
+
+ pynvml.nvmlInit()
+ def getFreeRatio(id):
+ handle = pynvml.nvmlDeviceGetHandleByIndex(id)
+ use = pynvml.nvmlDeviceGetUtilizationRates(handle)
+ ratio = 0.5*(float(use.gpu+float(use.memory)))
+ return ratio
+
+ deviceCount = pynvml.nvmlDeviceGetCount()
+ available = []
+ for i in range(deviceCount):
+ if getFreeRatio(i)<70:
+ available.append(i)
+ gpus = ''
+ for g in available:
+ gpus = gpus+str(g)+','
+ gpus = gpus[:-1]
+ return gpus
+
+def setgpu(gpuinput):
+ freeids = getFreeId()
+ if gpuinput=='all':
+ gpus = freeids
+ else:
+ gpus = gpuinput
+ if any([g not in freeids for g in gpus.split(',')]):
+ raise ValueError('gpu'+g+'is being used')
+ print('using gpu '+gpus)
+ os.environ['CUDA_VISIBLE_DEVICES']=gpus
+ return len(gpus.split(','))
+
+class Logger(object):
+ def __init__(self,logfile):
+ self.terminal = sys.stdout
+ self.log = open(logfile, "a")
+
+ def write(self, message):
+ self.terminal.write(message)
+ self.log.write(message)
+
+ def flush(self):
+ #this flush method is needed for python 3 compatibility.
+ #this handles the flush command by doing nothing.
+ #you might want to specify some extra behavior here.
+ pass
+
+
+def split4(data, max_stride, margin):
+ splits = []
+ data = torch.Tensor.numpy(data)
+ _,c, z, h, w = data.shape
+
+ w_width = np.ceil(float(w / 2 + margin)/max_stride).astype('int')*max_stride
+ h_width = np.ceil(float(h / 2 + margin)/max_stride).astype('int')*max_stride
+ pad = int(np.ceil(float(z)/max_stride)*max_stride)-z
+ leftpad = pad/2
+ pad = [[0,0],[0,0],[leftpad,pad-leftpad],[0,0],[0,0]]
+ data = np.pad(data,pad,'constant',constant_values=-1)
+ data = torch.from_numpy(data)
+ splits.append(data[:, :, :, :h_width, :w_width])
+ splits.append(data[:, :, :, :h_width, -w_width:])
+ splits.append(data[:, :, :, -h_width:, :w_width])
+ splits.append(data[:, :, :, -h_width:, -w_width:])
+
+ return torch.cat(splits, 0)
+
+def combine4(output, h, w):
+ splits = []
+ for i in range(len(output)):
+ splits.append(output[i])
+
+ output = np.zeros((
+ splits[0].shape[0],
+ h,
+ w,
+ splits[0].shape[3],
+ splits[0].shape[4]), np.float32)
+
+ h0 = output.shape[1] / 2
+ h1 = output.shape[1] - h0
+ w0 = output.shape[2] / 2
+ w1 = output.shape[2] - w0
+
+ splits[0] = splits[0][:, :h0, :w0, :, :]
+ output[:, :h0, :w0, :, :] = splits[0]
+
+ splits[1] = splits[1][:, :h0, -w1:, :, :]
+ output[:, :h0, -w1:, :, :] = splits[1]
+
+ splits[2] = splits[2][:, -h1:, :w0, :, :]
+ output[:, -h1:, :w0, :, :] = splits[2]
+
+ splits[3] = splits[3][:, -h1:, -w1:, :, :]
+ output[:, -h1:, -w1:, :, :] = splits[3]
+
+ return output
+
+def split8(data, max_stride, margin):
+ splits = []
+ if isinstance(data, np.ndarray):
+ c, z, h, w = data.shape
+ else:
+ _,c, z, h, w = data.size()
+
+ z_width = np.ceil(float(z / 2 + margin)/max_stride).astype('int')*max_stride
+ w_width = np.ceil(float(w / 2 + margin)/max_stride).astype('int')*max_stride
+ h_width = np.ceil(float(h / 2 + margin)/max_stride).astype('int')*max_stride
+ for zz in [[0,z_width],[-z_width,None]]:
+ for hh in [[0,h_width],[-h_width,None]]:
+ for ww in [[0,w_width],[-w_width,None]]:
+ if isinstance(data, np.ndarray):
+ splits.append(data[np.newaxis, :, zz[0]:zz[1], hh[0]:hh[1], ww[0]:ww[1]])
+ else:
+ splits.append(data[:, :, zz[0]:zz[1], hh[0]:hh[1], ww[0]:ww[1]])
+
+
+ if isinstance(data, np.ndarray):
+ return np.concatenate(splits, 0)
+ else:
+ return torch.cat(splits, 0)
+
+
+
+def combine8(output, z, h, w):
+ splits = []
+ for i in range(len(output)):
+ splits.append(output[i])
+
+ output = np.zeros((
+ z,
+ h,
+ w,
+ splits[0].shape[3],
+ splits[0].shape[4]), np.float32)
+
+
+ z_width = z / 2
+ h_width = h / 2
+ w_width = w / 2
+ i = 0
+ for zz in [[0,z_width],[z_width-z,None]]:
+ for hh in [[0,h_width],[h_width-h,None]]:
+ for ww in [[0,w_width],[w_width-w,None]]:
+ output[zz[0]:zz[1], hh[0]:hh[1], ww[0]:ww[1], :, :] = splits[i][zz[0]:zz[1], hh[0]:hh[1], ww[0]:ww[1], :, :]
+ i = i+1
+
+ return output
+
+
+def split16(data, max_stride, margin):
+ splits = []
+ _,c, z, h, w = data.size()
+
+ z_width = np.ceil(float(z / 4 + margin)/max_stride).astype('int')*max_stride
+ z_pos = [z*3/8-z_width/2,
+ z*5/8-z_width/2]
+ h_width = np.ceil(float(h / 2 + margin)/max_stride).astype('int')*max_stride
+ w_width = np.ceil(float(w / 2 + margin)/max_stride).astype('int')*max_stride
+ for zz in [[0,z_width],[z_pos[0],z_pos[0]+z_width],[z_pos[1],z_pos[1]+z_width],[-z_width,None]]:
+ for hh in [[0,h_width],[-h_width,None]]:
+ for ww in [[0,w_width],[-w_width,None]]:
+ splits.append(data[:, :, zz[0]:zz[1], hh[0]:hh[1], ww[0]:ww[1]])
+
+ return torch.cat(splits, 0)
+
+def combine16(output, z, h, w):
+ splits = []
+ for i in range(len(output)):
+ splits.append(output[i])
+
+ output = np.zeros((
+ z,
+ h,
+ w,
+ splits[0].shape[3],
+ splits[0].shape[4]), np.float32)
+
+
+ z_width = z / 4
+ h_width = h / 2
+ w_width = w / 2
+ splitzstart = splits[0].shape[0]/2-z_width/2
+ z_pos = [z*3/8-z_width/2,
+ z*5/8-z_width/2]
+ i = 0
+ for zz,zz2 in zip([[0,z_width],[z_width,z_width*2],[z_width*2,z_width*3],[z_width*3-z,None]],
+ [[0,z_width],[splitzstart,z_width+splitzstart],[splitzstart,z_width+splitzstart],[z_width*3-z,None]]):
+ for hh in [[0,h_width],[h_width-h,None]]:
+ for ww in [[0,w_width],[w_width-w,None]]:
+ output[zz[0]:zz[1], hh[0]:hh[1], ww[0]:ww[1], :, :] = splits[i][zz2[0]:zz2[1], hh[0]:hh[1], ww[0]:ww[1], :, :]
+ i = i+1
+
+ return output
+
+def split32(data, max_stride, margin):
+ splits = []
+ _,c, z, h, w = data.size()
+
+ z_width = np.ceil(float(z / 2 + margin)/max_stride).astype('int')*max_stride
+ w_width = np.ceil(float(w / 4 + margin)/max_stride).astype('int')*max_stride
+ h_width = np.ceil(float(h / 4 + margin)/max_stride).astype('int')*max_stride
+
+ w_pos = [w*3/8-w_width/2,
+ w*5/8-w_width/2]
+ h_pos = [h*3/8-h_width/2,
+ h*5/8-h_width/2]
+
+ for zz in [[0,z_width],[-z_width,None]]:
+ for hh in [[0,h_width],[h_pos[0],h_pos[0]+h_width],[h_pos[1],h_pos[1]+h_width],[-h_width,None]]:
+ for ww in [[0,w_width],[w_pos[0],w_pos[0]+w_width],[w_pos[1],w_pos[1]+w_width],[-w_width,None]]:
+ splits.append(data[:, :, zz[0]:zz[1], hh[0]:hh[1], ww[0]:ww[1]])
+
+ return torch.cat(splits, 0)
+
+def combine32(splits, z, h, w):
+
+ output = np.zeros((
+ z,
+ h,
+ w,
+ splits[0].shape[3],
+ splits[0].shape[4]), np.float32)
+
+
+ z_width = int(np.ceil(float(z) / 2))
+ h_width = int(np.ceil(float(h) / 4))
+ w_width = int(np.ceil(float(w) / 4))
+ splithstart = splits[0].shape[1]/2-h_width/2
+ splitwstart = splits[0].shape[2]/2-w_width/2
+
+ i = 0
+ for zz in [[0,z_width],[z_width-z,None]]:
+
+ for hh,hh2 in zip([[0,h_width],[h_width,h_width*2],[h_width*2,h_width*3],[h_width*3-h,None]],
+ [[0,h_width],[splithstart,h_width+splithstart],[splithstart,h_width+splithstart],[h_width*3-h,None]]):
+
+ for ww,ww2 in zip([[0,w_width],[w_width,w_width*2],[w_width*2,w_width*3],[w_width*3-w,None]],
+ [[0,w_width],[splitwstart,w_width+splitwstart],[splitwstart,w_width+splitwstart],[w_width*3-w,None]]):
+
+ output[zz[0]:zz[1], hh[0]:hh[1], ww[0]:ww[1], :, :] = splits[i][zz[0]:zz[1], hh2[0]:hh2[1], ww2[0]:ww2[1], :, :]
+ i = i+1
+
+ return output
+
+
+
+def split64(data, max_stride, margin):
+ splits = []
+ _,c, z, h, w = data.size()
+
+ z_width = np.ceil(float(z / 4 + margin)/max_stride).astype('int')*max_stride
+ w_width = np.ceil(float(w / 4 + margin)/max_stride).astype('int')*max_stride
+ h_width = np.ceil(float(h / 4 + margin)/max_stride).astype('int')*max_stride
+
+ z_pos = [z*3/8-z_width/2,
+ z*5/8-z_width/2]
+ w_pos = [w*3/8-w_width/2,
+ w*5/8-w_width/2]
+ h_pos = [h*3/8-h_width/2,
+ h*5/8-h_width/2]
+
+ for zz in [[0,z_width],[z_pos[0],z_pos[0]+z_width],[z_pos[1],z_pos[1]+z_width],[-z_width,None]]:
+ for hh in [[0,h_width],[h_pos[0],h_pos[0]+h_width],[h_pos[1],h_pos[1]+h_width],[-h_width,None]]:
+ for ww in [[0,w_width],[w_pos[0],w_pos[0]+w_width],[w_pos[1],w_pos[1]+w_width],[-w_width,None]]:
+ splits.append(data[:, :, zz[0]:zz[1], hh[0]:hh[1], ww[0]:ww[1]])
+
+ return torch.cat(splits, 0)
+
+def combine64(output, z, h, w):
+ splits = []
+ for i in range(len(output)):
+ splits.append(output[i])
+
+ output = np.zeros((
+ z,
+ h,
+ w,
+ splits[0].shape[3],
+ splits[0].shape[4]), np.float32)
+
+
+ z_width = int(np.ceil(float(z) / 4))
+ h_width = int(np.ceil(float(h) / 4))
+ w_width = int(np.ceil(float(w) / 4))
+ splitzstart = splits[0].shape[0]/2-z_width/2
+ splithstart = splits[0].shape[1]/2-h_width/2
+ splitwstart = splits[0].shape[2]/2-w_width/2
+
+ i = 0
+ for zz,zz2 in zip([[0,z_width],[z_width,z_width*2],[z_width*2,z_width*3],[z_width*3-z,None]],
+ [[0,z_width],[splitzstart,z_width+splitzstart],[splitzstart,z_width+splitzstart],[z_width*3-z,None]]):
+
+ for hh,hh2 in zip([[0,h_width],[h_width,h_width*2],[h_width*2,h_width*3],[h_width*3-h,None]],
+ [[0,h_width],[splithstart,h_width+splithstart],[splithstart,h_width+splithstart],[h_width*3-h,None]]):
+
+ for ww,ww2 in zip([[0,w_width],[w_width,w_width*2],[w_width*2,w_width*3],[w_width*3-w,None]],
+ [[0,w_width],[splitwstart,w_width+splitwstart],[splitwstart,w_width+splitwstart],[w_width*3-w,None]]):
+
+ output[zz[0]:zz[1], hh[0]:hh[1], ww[0]:ww[1], :, :] = splits[i][zz2[0]:zz2[1], hh2[0]:hh2[1], ww2[0]:ww2[1], :, :]
+ i = i+1
+
+ return output
diff --git a/training/classifier/valsplit.npy b/training/classifier/valsplit.npy
new file mode 100644
index 0000000..a6aa141
Binary files /dev/null and b/training/classifier/valsplit.npy differ
diff --git a/training/config_training.py b/training/config_training.py
new file mode 100644
index 0000000..20cd7e2
--- /dev/null
+++ b/training/config_training.py
@@ -0,0 +1,17 @@
+config = {'stage1_data_path':'/work/DataBowl3/stage1/stage1/',
+ 'luna_raw':'/work/DataBowl3/luna/raw/',
+ 'luna_segment':'/work/DataBowl3/luna/seg-lungs-LUNA16/',
+
+ 'luna_data':'/work/DataBowl3/luna/allset',
+ 'preprocess_result_path':'/work/DataBowl3/stage1/preprocess/',
+
+ 'luna_abbr':'./detector/labels/shorter.csv',
+ 'luna_label':'./detector/labels/lunaqualified.csv',
+ 'stage1_annos_path':['./detector/labels/label_job5.csv',
+ './detector/labels/label_job4_2.csv',
+ './detector/labels/label_job4_1.csv',
+ './detector/labels/label_job0.csv',
+ './detector/labels/label_qualified.csv'],
+ 'bbox_path':'../detector/results/res18/bbox/',
+ 'preprocessing_backend':'python'
+ }
diff --git a/training/detector/data.py b/training/detector/data.py
new file mode 100644
index 0000000..9cdff4f
--- /dev/null
+++ b/training/detector/data.py
@@ -0,0 +1,397 @@
+import numpy as np
+import torch
+from torch.utils.data import Dataset
+import os
+import time
+import collections
+import random
+from layers import iou
+from scipy.ndimage import zoom
+import warnings
+from scipy.ndimage.interpolation import rotate
+
+class DataBowl3Detector(Dataset):
+ def __init__(self, data_dir, split_path, config, phase = 'train',split_comber=None):
+ assert(phase == 'train' or phase == 'val' or phase == 'test')
+ self.phase = phase
+ self.max_stride = config['max_stride']
+ self.stride = config['stride']
+ sizelim = config['sizelim']/config['reso']
+ sizelim2 = config['sizelim2']/config['reso']
+ sizelim3 = config['sizelim3']/config['reso']
+ self.blacklist = config['blacklist']
+ self.isScale = config['aug_scale']
+ self.r_rand = config['r_rand_crop']
+ self.augtype = config['augtype']
+ self.pad_value = config['pad_value']
+ self.split_comber = split_comber
+ idcs = np.load(split_path)
+ if phase!='test':
+ idcs = [f for f in idcs if (f not in self.blacklist)]
+
+ self.filenames = [os.path.join(data_dir, '%s_clean.npy' % idx) for idx in idcs]
+ self.kagglenames = [f for f in self.filenames if len(f.split('/')[-1].split('_')[0])>20]
+ self.lunanames = [f for f in self.filenames if len(f.split('/')[-1].split('_')[0])<20]
+
+ labels = []
+
+ for idx in idcs:
+ l = np.load(os.path.join(data_dir, '%s_label.npy' %idx))
+ if np.all(l==0):
+ l=np.array([])
+ labels.append(l)
+
+ self.sample_bboxes = labels
+ if self.phase != 'test':
+ self.bboxes = []
+ for i, l in enumerate(labels):
+ if len(l) > 0 :
+ for t in l:
+ if t[3]>sizelim:
+ self.bboxes.append([np.concatenate([[i],t])])
+ if t[3]>sizelim2:
+ self.bboxes+=[[np.concatenate([[i],t])]]*2
+ if t[3]>sizelim3:
+ self.bboxes+=[[np.concatenate([[i],t])]]*4
+ self.bboxes = np.concatenate(self.bboxes,axis = 0)
+
+ self.crop = Crop(config)
+ self.label_mapping = LabelMapping(config, self.phase)
+
+ def __getitem__(self, idx,split=None):
+ t = time.time()
+ np.random.seed(int(str(t%1)[2:7]))#seed according to time
+
+ isRandomImg = False
+ if self.phase !='test':
+ if idx>=len(self.bboxes):
+ isRandom = True
+ idx = idx%len(self.bboxes)
+ isRandomImg = np.random.randint(2)
+ else:
+ isRandom = False
+ else:
+ isRandom = False
+
+ if self.phase != 'test':
+ if not isRandomImg:
+ bbox = self.bboxes[idx]
+ filename = self.filenames[int(bbox[0])]
+ imgs = np.load(filename)
+ bboxes = self.sample_bboxes[int(bbox[0])]
+ isScale = self.augtype['scale'] and (self.phase=='train')
+ sample, target, bboxes, coord = self.crop(imgs, bbox[1:], bboxes,isScale,isRandom)
+ if self.phase=='train' and not isRandom:
+ sample, target, bboxes, coord = augment(sample, target, bboxes, coord,
+ ifflip = self.augtype['flip'], ifrotate=self.augtype['rotate'], ifswap = self.augtype['swap'])
+ else:
+ randimid = np.random.randint(len(self.kagglenames))
+ filename = self.kagglenames[randimid]
+ imgs = np.load(filename)
+ bboxes = self.sample_bboxes[randimid]
+ isScale = self.augtype['scale'] and (self.phase=='train')
+ sample, target, bboxes, coord = self.crop(imgs, [], bboxes,isScale=False,isRand=True)
+ label = self.label_mapping(sample.shape[1:], target, bboxes)
+ sample = (sample.astype(np.float32)-128)/128
+ #if filename in self.kagglenames and self.phase=='train':
+ # label[label==-1]=0
+ return torch.from_numpy(sample), torch.from_numpy(label), coord
+ else:
+ imgs = np.load(self.filenames[idx])
+ bboxes = self.sample_bboxes[idx]
+ nz, nh, nw = imgs.shape[1:]
+ pz = int(np.ceil(float(nz) / self.stride)) * self.stride
+ ph = int(np.ceil(float(nh) / self.stride)) * self.stride
+ pw = int(np.ceil(float(nw) / self.stride)) * self.stride
+ imgs = np.pad(imgs, [[0,0],[0, pz - nz], [0, ph - nh], [0, pw - nw]], 'constant',constant_values = self.pad_value)
+
+ xx,yy,zz = np.meshgrid(np.linspace(-0.5,0.5,imgs.shape[1]/self.stride),
+ np.linspace(-0.5,0.5,imgs.shape[2]/self.stride),
+ np.linspace(-0.5,0.5,imgs.shape[3]/self.stride),indexing ='ij')
+ coord = np.concatenate([xx[np.newaxis,...], yy[np.newaxis,...],zz[np.newaxis,:]],0).astype('float32')
+ imgs, nzhw = self.split_comber.split(imgs)
+ coord2, nzhw2 = self.split_comber.split(coord,
+ side_len = self.split_comber.side_len/self.stride,
+ max_stride = self.split_comber.max_stride/self.stride,
+ margin = self.split_comber.margin/self.stride)
+ assert np.all(nzhw==nzhw2)
+ imgs = (imgs.astype(np.float32)-128)/128
+ return torch.from_numpy(imgs), bboxes, torch.from_numpy(coord2), np.array(nzhw)
+
+ def __len__(self):
+ if self.phase == 'train':
+ return len(self.bboxes)/(1-self.r_rand)
+ elif self.phase =='val':
+ return len(self.bboxes)
+ else:
+ return len(self.sample_bboxes)
+
+
+def augment(sample, target, bboxes, coord, ifflip = True, ifrotate=True, ifswap = True):
+ # angle1 = np.random.rand()*180
+ if ifrotate:
+ validrot = False
+ counter = 0
+ while not validrot:
+ newtarget = np.copy(target)
+ angle1 = np.random.rand()*180
+ size = np.array(sample.shape[2:4]).astype('float')
+ rotmat = np.array([[np.cos(angle1/180*np.pi),-np.sin(angle1/180*np.pi)],[np.sin(angle1/180*np.pi),np.cos(angle1/180*np.pi)]])
+ newtarget[1:3] = np.dot(rotmat,target[1:3]-size/2)+size/2
+ if np.all(newtarget[:3]>target[3]) and np.all(newtarget[:3]< np.array(sample.shape[1:4])-newtarget[3]):
+ validrot = True
+ target = newtarget
+ sample = rotate(sample,angle1,axes=(2,3),reshape=False)
+ coord = rotate(coord,angle1,axes=(2,3),reshape=False)
+ for box in bboxes:
+ box[1:3] = np.dot(rotmat,box[1:3]-size/2)+size/2
+ else:
+ counter += 1
+ if counter ==3:
+ break
+ if ifswap:
+ if sample.shape[1]==sample.shape[2] and sample.shape[1]==sample.shape[3]:
+ axisorder = np.random.permutation(3)
+ sample = np.transpose(sample,np.concatenate([[0],axisorder+1]))
+ coord = np.transpose(coord,np.concatenate([[0],axisorder+1]))
+ target[:3] = target[:3][axisorder]
+ bboxes[:,:3] = bboxes[:,:3][:,axisorder]
+
+ if ifflip:
+# flipid = np.array([np.random.randint(2),np.random.randint(2),np.random.randint(2)])*2-1
+ flipid = np.array([1,np.random.randint(2),np.random.randint(2)])*2-1
+ sample = np.ascontiguousarray(sample[:,::flipid[0],::flipid[1],::flipid[2]])
+ coord = np.ascontiguousarray(coord[:,::flipid[0],::flipid[1],::flipid[2]])
+ for ax in range(3):
+ if flipid[ax]==-1:
+ target[ax] = np.array(sample.shape[ax+1])-target[ax]
+ bboxes[:,ax]= np.array(sample.shape[ax+1])-bboxes[:,ax]
+ return sample, target, bboxes, coord
+
+class Crop(object):
+ def __init__(self, config):
+ self.crop_size = config['crop_size']
+ self.bound_size = config['bound_size']
+ self.stride = config['stride']
+ self.pad_value = config['pad_value']
+ def __call__(self, imgs, target, bboxes,isScale=False,isRand=False):
+ if isScale:
+ radiusLim = [8.,120.]
+ scaleLim = [0.75,1.25]
+ scaleRange = [np.min([np.max([(radiusLim[0]/target[3]),scaleLim[0]]),1])
+ ,np.max([np.min([(radiusLim[1]/target[3]),scaleLim[1]]),1])]
+ scale = np.random.rand()*(scaleRange[1]-scaleRange[0])+scaleRange[0]
+ crop_size = (np.array(self.crop_size).astype('float')/scale).astype('int')
+ else:
+ crop_size=self.crop_size
+ bound_size = self.bound_size
+ target = np.copy(target)
+ bboxes = np.copy(bboxes)
+
+ start = []
+ for i in range(3):
+ if not isRand:
+ r = target[3] / 2
+ s = np.floor(target[i] - r)+ 1 - bound_size
+ e = np.ceil (target[i] + r)+ 1 + bound_size - crop_size[i]
+ else:
+ s = np.max([imgs.shape[i+1]-crop_size[i]/2,imgs.shape[i+1]/2+bound_size])
+ e = np.min([crop_size[i]/2, imgs.shape[i+1]/2-bound_size])
+ target = np.array([np.nan,np.nan,np.nan,np.nan])
+ if s>e:
+ start.append(np.random.randint(e,s))#!
+ else:
+ start.append(int(target[i])-crop_size[i]/2+np.random.randint(-bound_size/2,bound_size/2))
+
+
+ normstart = np.array(start).astype('float32')/np.array(imgs.shape[1:])-0.5
+ normsize = np.array(crop_size).astype('float32')/np.array(imgs.shape[1:])
+ xx,yy,zz = np.meshgrid(np.linspace(normstart[0],normstart[0]+normsize[0],self.crop_size[0]/self.stride),
+ np.linspace(normstart[1],normstart[1]+normsize[1],self.crop_size[1]/self.stride),
+ np.linspace(normstart[2],normstart[2]+normsize[2],self.crop_size[2]/self.stride),indexing ='ij')
+ coord = np.concatenate([xx[np.newaxis,...], yy[np.newaxis,...],zz[np.newaxis,:]],0).astype('float32')
+
+ pad = []
+ pad.append([0,0])
+ for i in range(3):
+ leftpad = max(0,-start[i])
+ rightpad = max(0,start[i]+crop_size[i]-imgs.shape[i+1])
+ pad.append([leftpad,rightpad])
+ crop = imgs[:,
+ max(start[0],0):min(start[0] + crop_size[0],imgs.shape[1]),
+ max(start[1],0):min(start[1] + crop_size[1],imgs.shape[2]),
+ max(start[2],0):min(start[2] + crop_size[2],imgs.shape[3])]
+ crop = np.pad(crop,pad,'constant',constant_values =self.pad_value)
+ for i in range(3):
+ target[i] = target[i] - start[i]
+ for i in range(len(bboxes)):
+ for j in range(3):
+ bboxes[i][j] = bboxes[i][j] - start[j]
+
+ if isScale:
+ with warnings.catch_warnings():
+ warnings.simplefilter("ignore")
+ crop = zoom(crop,[1,scale,scale,scale],order=1)
+ newpad = self.crop_size[0]-crop.shape[1:][0]
+ if newpad<0:
+ crop = crop[:,:-newpad,:-newpad,:-newpad]
+ elif newpad>0:
+ pad2 = [[0,0],[0,newpad],[0,newpad],[0,newpad]]
+ crop = np.pad(crop,pad2,'constant',constant_values =self.pad_value)
+ for i in range(4):
+ target[i] = target[i]*scale
+ for i in range(len(bboxes)):
+ for j in range(4):
+ bboxes[i][j] = bboxes[i][j]*scale
+ return crop, target, bboxes, coord
+
+class LabelMapping(object):
+ def __init__(self, config, phase):
+ self.stride = np.array(config['stride'])
+ self.num_neg = int(config['num_neg'])
+ self.th_neg = config['th_neg']
+ self.anchors = np.asarray(config['anchors'])
+ self.phase = phase
+ if phase == 'train':
+ self.th_pos = config['th_pos_train']
+ elif phase == 'val':
+ self.th_pos = config['th_pos_val']
+
+
+ def __call__(self, input_size, target, bboxes):
+ stride = self.stride
+ num_neg = self.num_neg
+ th_neg = self.th_neg
+ anchors = self.anchors
+ th_pos = self.th_pos
+
+ output_size = []
+ for i in range(3):
+ assert(input_size[i] % stride == 0)
+ output_size.append(input_size[i] / stride)
+
+ label = -1 * np.ones(output_size + [len(anchors), 5], np.float32)
+ offset = ((stride.astype('float')) - 1) / 2
+ oz = np.arange(offset, offset + stride * (output_size[0] - 1) + 1, stride)
+ oh = np.arange(offset, offset + stride * (output_size[1] - 1) + 1, stride)
+ ow = np.arange(offset, offset + stride * (output_size[2] - 1) + 1, stride)
+
+ for bbox in bboxes:
+ for i, anchor in enumerate(anchors):
+ iz, ih, iw = select_samples(bbox, anchor, th_neg, oz, oh, ow)
+ label[iz, ih, iw, i, 0] = 0
+
+ if self.phase == 'train' and self.num_neg > 0:
+ neg_z, neg_h, neg_w, neg_a = np.where(label[:, :, :, :, 0] == -1)
+ neg_idcs = random.sample(range(len(neg_z)), min(num_neg, len(neg_z)))
+ neg_z, neg_h, neg_w, neg_a = neg_z[neg_idcs], neg_h[neg_idcs], neg_w[neg_idcs], neg_a[neg_idcs]
+ label[:, :, :, :, 0] = 0
+ label[neg_z, neg_h, neg_w, neg_a, 0] = -1
+
+ if np.isnan(target[0]):
+ return label
+ iz, ih, iw, ia = [], [], [], []
+ for i, anchor in enumerate(anchors):
+ iiz, iih, iiw = select_samples(target, anchor, th_pos, oz, oh, ow)
+ iz.append(iiz)
+ ih.append(iih)
+ iw.append(iiw)
+ ia.append(i * np.ones((len(iiz),), np.int64))
+ iz = np.concatenate(iz, 0)
+ ih = np.concatenate(ih, 0)
+ iw = np.concatenate(iw, 0)
+ ia = np.concatenate(ia, 0)
+ flag = True
+ if len(iz) == 0:
+ pos = []
+ for i in range(3):
+ pos.append(max(0, int(np.round((target[i] - offset) / stride))))
+ idx = np.argmin(np.abs(np.log(target[3] / anchors)))
+ pos.append(idx)
+ flag = False
+ else:
+ idx = random.sample(range(len(iz)), 1)[0]
+ pos = [iz[idx], ih[idx], iw[idx], ia[idx]]
+ dz = (target[0] - oz[pos[0]]) / anchors[pos[3]]
+ dh = (target[1] - oh[pos[1]]) / anchors[pos[3]]
+ dw = (target[2] - ow[pos[2]]) / anchors[pos[3]]
+ dd = np.log(target[3] / anchors[pos[3]])
+ label[pos[0], pos[1], pos[2], pos[3], :] = [1, dz, dh, dw, dd]
+ return label
+
+def select_samples(bbox, anchor, th, oz, oh, ow):
+ z, h, w, d = bbox
+ max_overlap = min(d, anchor)
+ min_overlap = np.power(max(d, anchor), 3) * th / max_overlap / max_overlap
+ if min_overlap > max_overlap:
+ return np.zeros((0,), np.int64), np.zeros((0,), np.int64), np.zeros((0,), np.int64)
+ else:
+ s = z - 0.5 * np.abs(d - anchor) - (max_overlap - min_overlap)
+ e = z + 0.5 * np.abs(d - anchor) + (max_overlap - min_overlap)
+ mz = np.logical_and(oz >= s, oz <= e)
+ iz = np.where(mz)[0]
+
+ s = h - 0.5 * np.abs(d - anchor) - (max_overlap - min_overlap)
+ e = h + 0.5 * np.abs(d - anchor) + (max_overlap - min_overlap)
+ mh = np.logical_and(oh >= s, oh <= e)
+ ih = np.where(mh)[0]
+
+ s = w - 0.5 * np.abs(d - anchor) - (max_overlap - min_overlap)
+ e = w + 0.5 * np.abs(d - anchor) + (max_overlap - min_overlap)
+ mw = np.logical_and(ow >= s, ow <= e)
+ iw = np.where(mw)[0]
+
+ if len(iz) == 0 or len(ih) == 0 or len(iw) == 0:
+ return np.zeros((0,), np.int64), np.zeros((0,), np.int64), np.zeros((0,), np.int64)
+
+ lz, lh, lw = len(iz), len(ih), len(iw)
+ iz = iz.reshape((-1, 1, 1))
+ ih = ih.reshape((1, -1, 1))
+ iw = iw.reshape((1, 1, -1))
+ iz = np.tile(iz, (1, lh, lw)).reshape((-1))
+ ih = np.tile(ih, (lz, 1, lw)).reshape((-1))
+ iw = np.tile(iw, (lz, lh, 1)).reshape((-1))
+ centers = np.concatenate([
+ oz[iz].reshape((-1, 1)),
+ oh[ih].reshape((-1, 1)),
+ ow[iw].reshape((-1, 1))], axis = 1)
+
+ r0 = anchor / 2
+ s0 = centers - r0
+ e0 = centers + r0
+
+ r1 = d / 2
+ s1 = bbox[:3] - r1
+ s1 = s1.reshape((1, -1))
+ e1 = bbox[:3] + r1
+ e1 = e1.reshape((1, -1))
+
+ overlap = np.maximum(0, np.minimum(e0, e1) - np.maximum(s0, s1))
+
+ intersection = overlap[:, 0] * overlap[:, 1] * overlap[:, 2]
+ union = anchor * anchor * anchor + d * d * d - intersection
+
+ iou = intersection / union
+
+ mask = iou >= th
+ #if th > 0.4:
+ # if np.sum(mask) == 0:
+ # print(['iou not large', iou.max()])
+ # else:
+ # print(['iou large', iou[mask]])
+ iz = iz[mask]
+ ih = ih[mask]
+ iw = iw[mask]
+ return iz, ih, iw
+
+def collate(batch):
+ if torch.is_tensor(batch[0]):
+ return [b.unsqueeze(0) for b in batch]
+ elif isinstance(batch[0], np.ndarray):
+ return batch
+ elif isinstance(batch[0], int):
+ return torch.LongTensor(batch)
+ elif isinstance(batch[0], collections.Iterable):
+ transposed = zip(*batch)
+ return [collate(samples) for samples in transposed]
+
diff --git a/training/detector/detect.py b/training/detector/detect.py
new file mode 100644
index 0000000..378d285
--- /dev/null
+++ b/training/detector/detect.py
@@ -0,0 +1,60 @@
+import numpy as np
+from layers import nms, iou, acc
+import time
+import multiprocessing as mp
+
+save_dir = 'results/ma_offset40_res_n6_100-1/'
+pbb = np.load(save_dir + 'pbb.npy')
+lbb = np.load(save_dir + 'lbb.npy')
+
+conf_th = [-1, 0, 1]
+nms_th = [0.3, 0.5, 0.7]
+detect_th = [0.2, 0.3]
+def mp_get_pr(conf_th, nms_th, detect_th, num_procs = 64):
+ start_time = time.time()
+
+ num_samples = len(pbb)
+ split_size = int(np.ceil(float(num_samples) / num_procs))
+ num_procs = int(np.ceil(float(num_samples) / split_size))
+
+ manager = mp.Manager()
+ tp = manager.list(range(num_procs))
+ fp = manager.list(range(num_procs))
+ p = manager.list(range(num_procs))
+ procs = []
+ for pid in range(num_procs):
+ proc = mp.Process(
+ target = get_pr,
+ args = (
+ pbb[pid * split_size:min((pid + 1) * split_size, num_samples)],
+ lbb[pid * split_size:min((pid + 1) * split_size, num_samples)],
+ conf_th, nms_th, detect_th, pid, tp, fp, p))
+ procs.append(proc)
+ proc.start()
+
+ for proc in procs:
+ proc.join()
+
+ tp = np.sum(tp)
+ fp = np.sum(fp)
+ p = np.sum(p)
+
+ end_time = time.time()
+ print('conf_th %1.1f, nms_th %1.1f, detect_th %1.1f, tp %d, fp %d, p %d, recall %f, time %3.2f' % (conf_th, nms_th, detect_th, tp, fp, p, float(tp) / p, end_time - start_time))
+
+def get_pr(pbb, lbb, conf_th, nms_th, detect_th, pid, tp_list, fp_list, p_list):
+ tp, fp, p = 0, 0, 0
+ for i in range(len(pbb)):
+ tpi, fpi, pi = acc(pbb[i], lbb[i], conf_th, nms_th, detect_th)
+ tp += tpi
+ fp += fpi
+ p += pi
+ tp_list[pid] = tp
+ fp_list[pid] = fp
+ p_list[pid] = p
+
+if __name__ == '__main__':
+ for ct in conf_th:
+ for nt in nms_th:
+ for dt in detect_th:
+ mp_get_pr(ct, nt, dt)
diff --git a/training/detector/full.npy b/training/detector/full.npy
new file mode 100644
index 0000000..3e013d7
Binary files /dev/null and b/training/detector/full.npy differ
diff --git a/training/detector/kaggleluna_full.npy b/training/detector/kaggleluna_full.npy
new file mode 100644
index 0000000..b3ff74c
Binary files /dev/null and b/training/detector/kaggleluna_full.npy differ
diff --git a/training/detector/labels/annos.csv b/training/detector/labels/annos.csv
new file mode 100644
index 0000000..1d039c8
--- /dev/null
+++ b/training/detector/labels/annos.csv
@@ -0,0 +1,1187 @@
+seriesuid,coordX,coordY,coordZ,diameter_mm
+0,-128.6994211,-175.3192718,-298.3875064,5.651470635
+0,103.7836509,-211.9251487,-227.12125,4.224708481
+2,69.63901724,-140.9445859,876.3744957,5.786347814
+5,-24.0138242,192.1024053,-391.0812764,8.143261683
+5,2.441546798,172.4648812,-405.4937318,18.54514997
+5,90.93171321,149.0272657,-426.5447146,18.20857028
+5,89.54076865,196.4051593,-515.0733216,16.38127631
+7,81.50964574,54.9572186,-150.3464233,10.36232088
+10,105.0557924,19.82526014,-91.24725078,21.08961863
+12,-124.8342624,127.2471546,-473.0644785,10.46585391
+14,-106.9013014,21.92298672,-126.9169003,9.745258507
+16,2.263815885,33.52641757,-170.6369497,7.16854239
+17,-70.55088903,66.35948368,-160.9429324,6.642184792
+17,-70.66062844,-29.54777007,-106.9030825,4.543419878
+19,-96.43953415,9.736190398,-175.0375714,6.753816666
+20,-57.08718036,74.25926591,1790.494057,13.69356578
+21,-98.1359775,-72.86779248,-221.822772,18.12790811
+22,122.0789199,-175.8341133,-193.8795594,5.084404982
+22,100.9322734,-179.4539814,-222.7930698,5.64474117
+22,-46.7837286,-66.973694,-207.4908964,4.214452054
+22,-69.12656791,-80.56714288,-189.8066129,8.648009287
+22,-108.0728115,-147.1544803,-186.0432849,7.285341553
+22,82.22918083,-82.37619066,-177.897695,6.140896043
+24,-100.5679445,67.26051683,-231.816619,6.440878725
+25,42.5741545,90.26755201,-84.81106034,5.916173884
+26,46.18853869,48.40280596,-108.5786324,13.59647134
+26,36.39204443,76.77166265,-123.3219112,4.343199739
+28,-38.09602046,-106.7054337,-139.5484666,13.68374597
+30,136.4340587,117.7655789,-181.9478171,4.681381581
+31,-80.95185933,10.34287843,-28.39915701,9.454440433
+31,-117.0680571,40.04322699,-134.7403426,5.269627504
+32,100.1984998,28.86441794,-212.7880542,5.190273745
+32,98.79046698,9.538892661,-183.2404309,3.857518777
+32,15.76513311,83.8624806,-146.0988221,5.111033559
+34,47.67105722,37.64251989,-99.89039388,30.61040636
+34,-60.76413588,-66.43517038,-100.2050371,16.88290495
+35,-65.87013627,50.73044009,-90.80330387,5.915845183
+35,-105.9171192,-17.6565882,-105.0917524,5.48467872
+35,42.29613347,56.15173475,-84.66166226,6.47796611
+35,-137.5005674,-21.65360391,-152.0366379,4.362886498
+35,-26.86268253,38.52993743,-167.5018886,5.885443068
+35,71.39121262,10.55131442,-85.27847902,5.734744196
+35,59.89735907,41.71051844,-96.24057315,4.3556589
+35,99.37468119,23.94678445,-138.5658318,9.104624209
+37,97.37065917,38.38001233,-64.46956062,4.415940924
+37,91.00973801,75.27136367,-199.8623244,5.519376862
+37,-52.44600494,13.24618228,-100.2137946,5.492123714
+39,107.0091479,63.25134805,-169.9519302,5.165048038
+40,-127.5329894,-29.60790208,-253.6976163,8.269325422
+40,93.13888159,-5.652615166,-213.9106155,6.209760075
+40,75.45450371,7.903213687,-194.3685225,7.6317087
+41,-61.06388101,-9.479044949,-167.2364982,7.025592326
+41,103.0705158,68.40957144,-92.41774522,5.829699739
+41,-26.24101038,79.69154358,-62.01174178,5.241641609
+42,-34.49722741,-9.311874316,-37.44756628,7.360638607
+42,-72.83218702,24.89329087,-51.72437324,4.912791975
+43,86.40287315,50.87510892,-81.3868821,12.73358119
+47,-116.8346004,227.4323404,-565.6218654,4.910652503
+47,-32.66447114,188.3615147,-640.737396,4.468307428
+47,88.25600165,230.5158009,-623.295922,9.011764374
+47,55.71446565,190.7603968,-579.6542959,10.88873794
+47,-121.6502017,216.3673938,-635.5142522,4.355736429
+49,-63.09760599,-56.55503154,-332.9778338,10.33318806
+49,-164.3510309,-136.6619593,-301.5817285,9.220611088
+49,-141.7238666,-124.9488005,-251.3310155,6.054719899
+50,-68.62139433,-84.03463116,-160.5226706,6.334194889
+50,-28.36728411,-82.21130866,-206.4823356,6.607863144
+51,-117.722135,160.4941255,-688.2851649,15.34315352
+52,76.54060313,-104.9008899,-86.21061178,4.84697694
+53,-78.69731043,-95.41409843,-168.680412,6.000997888
+56,-86.89844846,-53.10326995,-130.0891571,5.118825049
+57,49.31293635,-63.21521025,-118.7995619,22.13322034
+59,-103.9504272,-156.4473234,-143.9506516,5.194045747
+59,63.57534973,-130.319172,-125.0296842,4.387576729
+60,-94.29246806,60.22561502,-261.2127762,14.19833109
+60,-54.61763177,59.35238726,-236.0747811,13.9323257
+61,-58.38635605,0.082104855,-247.7679608,14.16396307
+63,-144.2210822,76.8021616,-260.6565506,6.961023634
+63,-96.83727606,-5.571432326,-253.0544355,4.833889744
+63,-144.8248012,71.31022616,-251.0999717,5.050147896
+63,-147.2732369,-16.72239867,-240.7544685,7.196392768
+63,112.7053209,64.8630062,-243.8057686,5.898838135
+63,72.85764176,91.95800608,-225.1181458,5.997708724
+64,-104.5202654,-80.58695572,-206.7105258,4.868289382
+64,73.74147799,20.52463349,-144.2154706,4.859054017
+65,-129.0547255,-12.23855483,-79.4978846,21.82795321
+66,145.967465,-161.1976342,-312.0713474,6.378436317
+68,-86.7371531,50.43512096,-156.612762,9.259814
+68,78.93980901,15.80057403,-95.35623253,14.95279904
+68,-60.61494104,50.42874262,-95.98745681,6.736648953
+69,-61.38042695,-72.80237271,-230.3742024,5.174837024
+69,-55.4650503,-72.1326947,-264.3412335,5.600330272
+69,31.31603013,-141.7597373,-93.9202978,3.393985464
+69,75.17419134,-76.43875411,-262.349883,4.054585195
+69,79.7279097,-236.1324625,-149.6524383,4.732833115
+71,124.370439,-106.0114955,-208.2958333,4.492434135
+71,111.9984909,-148.5527622,-170.1697015,3.916276383
+71,-70.16527375,-144.9379752,-86.54947655,10.96737987
+74,59.1141461,-158.5772534,-118.037336,6.720277435
+75,44.01647614,-7.920203139,-249.6876651,7.60446251
+75,-96.96022013,48.93585032,-68.03842933,16.97755709
+76,104.7694388,-1.720163357,-204.3343503,4.887779405
+77,97.49024191,28.55020986,-160.5336443,8.842809348
+78,33.83282599,88.41158995,-101.7804814,10.4626083
+79,69.52897275,-24.4152887,-137.8211351,7.035809202
+79,87.16989338,16.38497348,-274.2034889,5.85837472
+80,-99.85852187,37.43405102,-170.4566088,12.3192364
+80,-78.66713641,66.42215895,-168.8716784,13.02514237
+81,-79.18515549,93.97389133,-146.3062085,5.317166147
+81,44.14055176,100.3832603,-139.8410947,6.133374031
+82,-96.46930419,-88.12896199,1131.113774,6.800248866
+83,80.77303275,-29.15344675,-85.55027647,3.611869871
+85,-32.10848635,-30.26543546,-219.5786756,4.978982963
+85,-94.29018316,70.67432635,-253.256346,4.843419619
+85,133.983223,16.50243609,-158.8158943,5.674730826
+85,-16.01619076,50.52094748,-137.5903435,4.907212712
+86,-93.52263469,-194.6344428,-191.5919406,6.134569156
+87,88.23145221,32.80911691,-77.98638617,5.05940652
+88,-107.8443234,9.187612266,-230.5331004,4.897802289
+88,93.0086447,14.09192582,-218.2554877,4.720442281
+90,-91.91936643,87.00392719,1453.777585,14.43967916
+90,-59.72321708,84.839226,1368.370353,9.769564126
+91,74.2822796,57.09404849,-122.279633,6.70661454
+93,-33.32584895,50.4405973,-253.8029719,11.3447991
+93,-57.18592317,78.72513926,-133.6241393,13.65181798
+94,-58.2494371,-98.05475684,-227.604282,4.402746921
+94,-61.47472636,-140.3727694,-59.31736202,9.326384983
+95,-119.4330363,-48.7962957,-223.600473,12.03514375
+95,-35.51923634,40.34791487,-72.19348873,7.183794081
+97,-84.04658072,-42.01536028,-146.8074,7.053719722
+97,-70.32309853,56.20438421,-82.47945755,7.888814398
+97,-86.85384308,15.04157401,-72.32680955,9.25825997
+97,99.63448881,-25.73228594,-199.6153564,6.779556482
+98,-109.1369335,-124.5550327,-105.8852679,14.15074869
+100,-41.39469558,-81.30460432,-238.141021,5.739194256
+101,-103.723003,153.3927131,-465.845305,11.13983165
+101,-80.44626828,183.9384127,-467.8757027,17.69382414
+102,88.82472816,-213.341493,168.2571724,17.74608206
+102,57.17854367,-191.0388202,182.1082155,10.07596577
+103,-120.9836813,177.1711523,-530.9680868,6.921521943
+105,53.27674099,66.29703219,-254.5379718,17.37441249
+107,110.2444818,-225.8683112,-184.3440648,4.937409282
+107,-91.21175481,-159.2195004,-181.0273265,6.310673697
+107,-62.9426951,-91.85733781,-154.3643203,11.68644494
+108,-108.127825,-176.5624058,-192.9633399,8.621579517
+114,97.37614851,-102.5986444,-156.3406252,11.2322969
+115,-108.0334716,59.54355435,-256.4077135,8.437996083
+115,106.6044712,-46.41062225,-181.2522845,5.235910569
+115,-72.97101044,49.02652606,-67.08815205,10.91366167
+117,-101.9672788,248.736321,-739.8746836,6.259551508
+118,-101.0050569,24.07044046,-108.7562821,11.62935127
+119,-73.28217211,46.20627483,-185.2274411,6.022565899
+120,-148.0814493,-165.0240818,-289.0138609,4.716992744
+120,156.4947772,-149.3952143,-280.7709302,6.049591287
+120,106.0772829,-209.9599669,-245.5249483,5.471134731
+121,67.92682992,-24.89511697,-78.85797979,16.59533492
+121,14.27208885,94.14615593,-129.5316415,3.904418305
+121,-71.71034314,-51.03435569,-60.04814098,6.288178284
+122,37.0690484,-156.5575996,959.5810338,7.3033558
+123,53.30850981,-93.95190759,-253.6684413,5.202649246
+123,-87.81822242,-240.437239,-153.8057486,5.901320414
+123,-106.0460276,-192.5404675,-155.2066788,3.888635523
+125,104.9934369,69.39425205,-122.7425876,5.686317218
+126,-76.86981076,-149.5342705,-127.5383708,18.79314938
+130,138.4754244,50.1395894,-311.3558523,16.18466141
+130,116.4755427,-19.95043225,-198.9967643,4.536882084
+135,-75.29240495,21.15278462,-199.692606,6.896207561
+138,91.41858153,-21.56714696,-257.7988959,24.77327957
+139,-10.02312089,95.43468299,-115.5338694,5.498132148
+139,84.43809487,41.64011864,-38.62495844,6.45617819
+140,-57.54166864,-23.88712628,-139.3714857,4.372179266
+140,-10.63664132,53.74246081,-60.36283743,4.223936088
+141,150.9859351,-134.5185043,-328.8678433,6.506928243
+141,74.32647971,-152.5691673,-178.2863299,5.851190527
+142,29.43814722,63.4969422,-196.6709143,5.209168076
+142,-100.5097932,29.32101972,-97.17804233,5.062185148
+142,-119.2839541,-23.22368795,-110.8177161,8.679781517
+142,-89.66859279,34.29905922,-128.5602482,23.48374545
+142,-75.73296957,35.285004,-185.380144,4.181187701
+142,-126.1625656,-0.397681495,-213.3227087,4.762202969
+144,58.51266333,75.79401283,-279.2924241,15.99235031
+145,-78.27791848,-61.2505383,-147.0934292,7.065657802
+146,-71.61430842,20.40693879,-22.78358686,17.34721239
+146,-54.48997947,41.59197595,-41.15781303,3.662351465
+147,38.14941728,1.80271657,-70.90735161,7.047024057
+148,-114.0871448,-229.0544486,-171.1804677,6.346289783
+150,118.0918135,196.2840721,-583.8597146,5.147276862
+150,164.7639846,204.6731739,-692.6948336,4.731109238
+150,-50.50497575,124.8450856,-550.3697203,6.867096006
+150,-64.867508,103.6062633,-620.0340436,3.253443196
+154,112.4969508,-43.72684601,-199.0055588,12.8170256
+154,104.3942446,-9.972464082,-183.3350265,9.843747171
+154,77.50052459,-36.4248749,-144.2257551,6.663525037
+154,-61.84947057,15.77948178,-113.5974073,5.758006712
+154,55.39113668,11.93657847,-63.1551208,13.73620925
+155,-88.25023673,-94.62918889,-169.2121709,6.085343495
+156,90.76420042,13.42579202,-161.1894594,6.901543658
+156,-83.56715969,69.86135283,-119.3583556,16.45094344
+157,-32.44901873,49.38239307,-60.31881666,24.28186352
+158,-57.43923954,131.2325201,-520.3592267,15.48525426
+159,-96.03191383,60.03021853,-227.4858932,4.46945041
+159,-97.15553193,-33.52680778,-220.9102515,4.97609166
+159,-60.48501225,95.33178835,-215.8217846,4.617203255
+160,-64.57029576,-64.34905382,-173.5655722,4.963355643
+160,-73.74416699,36.34720067,-146.6572802,7.125812147
+160,-99.82217711,82.20045747,-160.3782252,4.433065629
+160,114.3373054,-52.42864237,-205.2514715,5.612971703
+160,109.954732,67.37798105,-187.9100946,5.072213606
+160,121.5214666,60.77685417,-226.0365872,4.864259951
+161,-118.0353247,-3.2186828,-165.5819859,6.468256072
+161,-106.8106443,27.8632289,-154.8756784,5.509298811
+161,-76.98391685,81.55006658,-73.46885718,5.43507424
+167,-87.63095911,-25.15269986,-119.2177525,11.4755235
+168,-48.73057191,19.90509306,-97.41971618,7.765435432
+170,-58.64456388,29.43795597,-78.8440923,8.742043676
+172,39.29726212,69.52841861,-210.5451848,9.759961201
+172,-90.0716255,63.02506813,-162.4659197,4.290410287
+172,86.66388385,47.59551127,-94.13090031,4.190282988
+176,-105.4187651,250.8183267,-624.2090569,9.359117475
+176,-53.4094697,239.4490175,-635.4941475,9.376296072
+176,57.83232025,268.8908598,-646.4639133,8.15237846
+176,122.4122106,165.6107352,-683.3834284,7.428430647
+176,36.17618311,271.405521,-690.7770874,9.421061711
+178,-56.24973532,-75.22365785,-183.5827055,4.637327615
+178,116.2254123,-173.5753534,-162.7195162,7.318099839
+179,-25.82864181,-91.1680942,-200.1866058,9.587295623
+180,17.29473579,-80.60955607,-181.4152216,9.562175963
+181,76.6376056,-68.3923344,-220.5859873,6.940547015
+183,-62.4632701,40.61731074,-418.8345544,21.25611171
+185,-126.7777701,-9.907025513,-175.0163727,4.991565057
+187,-89.50837321,-219.1764409,-204.1231254,6.908606934
+188,100.6235685,64.75681577,-211.9604224,10.57235285
+188,-87.67439109,-12.69365522,-120.9322012,20.4841094
+190,38.16063294,-132.2282842,-198.8002432,8.833712029
+190,97.89985608,-130.7686347,-156.6501864,12.56457376
+191,-27.95756965,53.79011265,-10.40898875,6.250647306
+192,-109.7517763,-131.6996881,-216.9568763,6.367212147
+193,112.4519283,-57.33842196,-141.2823189,4.775243237
+194,-51.88965008,97.1144842,-115.6104374,16.33256347
+195,-106.0815728,-56.18920866,-179.184765,7.880768174
+195,95.99267245,75.81091807,-193.0071743,4.143870035
+195,-106.6074186,13.30759394,-194.0673055,5.108290964
+195,141.2692664,-4.147874764,-224.0220092,4.66199491
+195,112.662387,-63.4988029,-238.1679455,7.215827227
+196,84.48441941,182.3577437,-554.7284037,6.267755429
+196,-69.63476394,228.9381557,-603.0374367,4.397986174
+196,-94.5953571,177.6498386,-528.0518133,5.670704388
+196,-123.4290726,101.1391192,-548.1391139,3.879687831
+197,52.1565392,12.69280585,-35.912123,21.47561299
+197,126.454255,21.26837852,-130.8084904,6.661547445
+197,-76.00545815,38.00370105,-242.558351,6.463900827
+197,76.83900581,-32.77783779,-80.06591768,5.233376939
+197,-51.47470408,53.59606277,-83.70758676,4.500244204
+197,-27.09350963,30.33615286,-73.99322368,3.813182598
+197,162.1323087,-7.627735827,-214.2993486,4.994599024
+198,-107.4682246,-16.00795837,-124.3814417,3.851212212
+198,-55.79826686,27.52331317,-54.77526251,6.536524171
+199,72.28670656,76.90023946,-190.4589276,21.45372882
+199,23.49083071,-47.63390567,-172.2791417,8.785832848
+199,-47.40284557,-30.171209,-169.6239465,12.82311988
+201,-29.39234236,38.41896008,-51.14223,4.537177872
+201,-33.17172203,24.21759562,-20.51608372,5.983490254
+202,110.4185895,85.06714826,-175.3696326,5.808348361
+203,43.88129782,64.17904949,-232.5899014,5.925757611
+206,-115.7223995,35.61826614,-175.4716358,10.03093365
+206,-136.7078457,62.06070501,-99.27715843,18.38478817
+207,-27.97722814,-83.92404684,-269.020919,6.281626529
+207,155.3413899,-150.8678039,-343.484454,5.229396767
+209,-126.2838871,4.683453379,-155.2960218,4.803214362
+209,104.8509634,69.34115982,-148.9084074,4.326877582
+209,117.5353489,28.71672637,-121.227376,5.235946908
+210,-51.04382869,75.20020777,-101.5526036,14.83693973
+210,-80.27882566,76.47337026,-108.0625,4.844157662
+210,-116.2874457,21.16102581,-124.619925,10.88839157
+210,-111.1930507,-1.264504521,-138.6984478,17.39699158
+210,-92.25910919,-42.63590904,-145.6351351,4.595709259
+210,73.77454834,37.27831567,-118.3077904,8.648347161
+211,50.33716697,63.51366238,-75.98942194,4.064058796
+212,76.49433466,88.15768761,-193.1555684,19.0442187
+213,109.4990234,93.69210525,-269.0638976,5.832577347
+214,104.0876202,25.52198446,-140.171147,16.04323095
+215,-58.95432995,51.94459996,-59.38552081,9.494854536
+216,-43.91205948,-43.24151644,-141.6973546,9.147221174
+216,-36.51308198,-65.21501284,-124.4263249,14.61583872
+219,107.981511,-4.36735685,-124.106848,4.672138736
+219,71.12211478,103.5762892,-148.4515459,7.04604765
+219,49.9464803,39.21748433,-239.8346609,12.38102253
+219,72.37076198,83.67370356,-244.3847883,6.33705611
+219,-35.36902968,83.72542652,-150.2529177,7.025817316
+219,-41.69008438,-7.144610815,-158.7180743,7.670739872
+219,-33.72450557,-17.3035396,-103.0529877,4.517226352
+219,-10.6098601,61.08200309,-166.5353176,4.84811308
+219,-33.0757396,103.021741,-192.6359693,6.450730852
+219,-53.33179978,96.45855774,-226.2565169,10.98489943
+219,-60.85305037,-38.91766158,-205.682724,4.672156227
+219,109.4598251,-34.52836499,-188.547619,3.939481265
+221,97.58296617,41.96482868,-79.81459274,3.423341719
+221,70.09772041,-23.4790975,-142.6707459,4.216156288
+222,-46.82137782,80.98240214,-109.2275388,5.562150111
+223,-57.06218821,-2.42519767,-35.57766455,8.868454579
+223,-66.47429649,58.43968307,-109.3643906,25.87269662
+224,56.00355828,-42.3898391,-97.24818247,8.811296392
+225,-75.07441798,80.77730228,-125.3339445,8.315884851
+226,-43.54413253,-50.15803892,-146.6903955,3.975397996
+229,94.32108066,-21.41829214,-154.6986815,5.806583725
+230,65.1376641,43.75788979,-236.4710746,8.566001555
+231,56.20840547,86.34341278,-115.8675792,23.35064438
+232,134.4219361,86.57701746,-762.5944358,7.401764599
+232,-127.6916352,110.5885962,-739.9738785,5.744966449
+232,-50.33006209,88.30887267,-677.332466,3.439486702
+233,-78.50974455,-162.584138,-64.40943048,6.929649846
+233,82.60358264,-216.3818316,-151.0002647,5.22596183
+235,-100.6082859,94.59993686,-263.9090942,5.279110868
+236,138.8853876,-36.17927643,-198.6659593,4.895529998
+237,56.58885682,-67.46153204,-77.34666348,3.270466947
+237,38.83601126,104.8736883,-72.04062367,6.409813214
+240,-71.70939018,-47.08972918,-218.4168486,4.506689862
+240,34.65292887,18.54173,-79.08423032,4.812692889
+241,77.43647945,22.21703609,-194.8565238,8.875835636
+241,20.57233382,93.68779093,-181.0413165,6.974134428
+241,53.04979758,5.774405018,-159.5827607,6.49900752
+241,25.46898071,-15.96877128,-116.7001729,7.615286406
+242,-82.49078423,31.00113485,-213.6818417,14.15706867
+242,-36.36744189,-41.8952304,-147.4127015,17.15800497
+243,-46.59430055,64.33901696,-149.7871177,24.78201705
+245,-103.4902087,-63.80000006,-222.2229424,7.35278351
+246,-43.90685095,-74.65024942,-213.2556584,11.04800959
+246,51.89001754,-106.6204144,-180.5559271,5.808811273
+247,115.9854895,9.847305538,-210.8941679,4.450273187
+247,-114.9272123,-40.83007173,-167.9105444,4.049334725
+249,-64.79512505,-35.55654393,-65.40505764,11.47132343
+249,108.2379848,-23.00591217,-75.13184405,9.346613641
+249,-50.87414525,61.48907516,-138.6793414,7.822901747
+249,109.1514742,-27.15936266,-147.1130632,6.265028453
+249,49.1056976,58.58649113,-185.398676,5.072155337
+250,67.19434305,63.99802245,-246.1106238,13.05335657
+250,94.63511683,-17.37205941,-204.3961269,17.75323185
+251,91.8066639,-228.1486839,-206.7306038,15.48070961
+253,70.12569801,-37.51841728,-145.8086969,4.073945715
+253,-74.95237164,46.90988268,-285.5115615,4.277166591
+253,110.1006468,-57.64062374,-243.1164102,5.251013012
+253,-50.86871032,86.60666104,-145.7656656,9.772734741
+254,-110.5020624,84.49831867,1506.369708,5.304621719
+254,-49.20548545,92.92857185,1478.923267,5.719422603
+255,-81.59738505,57.28823522,-133.479575,5.617921172
+255,28.62300902,41.00929115,-155.4889456,5.88395182
+256,-60.49431739,70.54622166,-58.67519437,8.70905255
+257,-55.18838267,174.3893763,-405.7348248,10.93827513
+257,-100.5100772,179.7605127,-498.510449,5.357746933
+257,-87.27597336,163.0151729,-456.4501041,5.26273061
+257,79.03555701,209.8179057,-465.0624392,6.305539247
+258,-103.0536882,-65.26580979,-118.3045242,4.286161529
+260,-95.29757514,189.2305976,-500.4365795,7.794843882
+260,-106.9376643,142.6213881,-553.7500925,11.47520609
+261,-83.12026192,91.61578275,-320.3531873,7.90492271
+261,107.5055367,71.93790105,-278.241906,4.565784214
+263,-47.59725933,38.35581629,-259.5247127,6.704958329
+265,-96.19600129,-96.65249765,-324.2845499,4.502295592
+268,119.4417648,-124.5798429,-183.5276495,5.168489458
+268,-59.74501321,-186.7368963,-117.5250438,5.261510023
+268,99.55427087,-196.7161331,-96.1010188,5.831328901
+268,-29.1700199,-133.1657313,-41.27737383,5.842982096
+268,25.20531741,-125.3875332,-38.98208822,4.538549476
+269,125.72278,-65.38741378,-155.8430296,5.463268111
+272,-47.71460531,-32.47540199,-77.44002704,7.141617843
+273,16.03531414,67.91292767,-31.29420185,3.887997704
+274,-32.75374084,8.777235784,-111.7798254,6.975190342
+275,56.23980222,-92.28982952,-277.0985595,8.982986958
+277,121.1740107,74.57004217,-168.1036947,4.92742239
+277,96.66859593,37.64844408,-58.80225858,5.866256959
+278,-47.89877032,-10.22492024,-96.1136025,20.15998367
+279,-106.8617398,9.048151896,-122.3496855,23.68811013
+280,105.0927476,-12.11034538,-163.8563959,6.67566416
+280,-65.24188146,-2.009534031,-154.5988093,5.611381537
+280,95.50326213,50.83309312,-98.17735226,9.697334131
+280,-44.35081815,-2.878997069,-80.20624421,6.734930528
+280,-36.79299198,30.7687084,-78.63004564,7.21357337
+280,114.1812202,39.58850481,-77.01551257,6.554327379
+280,101.203838,25.22046529,-133.8132453,6.269450237
+280,99.7584658,42.83369719,-142.7906833,6.39203287
+280,76.62464946,-2.190466163,-170.1541606,5.512269698
+281,-106.3585085,-51.59739866,-166.4583333,4.311583799
+282,70.27851491,-52.13332395,-63.60156718,5.295986982
+283,-96.52133314,-61.02297366,-204.6272521,5.343956496
+283,-114.0292501,36.09563198,-281.6690246,7.754485276
+283,92.36574726,18.31481554,-84.53565705,9.642120967
+283,-71.01906551,-37.76752972,-133.5475427,4.93642793
+283,-85.4417408,-50.32069009,-177.4651732,6.32263359
+285,-147.9529673,-164.1694792,-273.4342411,5.898208305
+286,59.25687577,-34.72292702,-134.8379138,13.13641553
+286,78.29576032,-16.92867765,-163.9475346,19.34841823
+286,64.42984573,70.38559073,-216.6686873,20.52475616
+288,-72.92501601,196.8030244,-528.6920833,5.19625288
+288,101.5197074,172.2746015,-530.7701627,4.93269156
+289,-109.4034773,247.5094285,-743.5538024,4.872378109
+290,-87.98029816,-170.435691,-67.39794153,8.260459929
+291,-47.24454656,-63.24393196,-190.0773363,5.109990357
+292,73.10057831,22.12013499,-219.3862128,8.10334672
+292,-93.90331541,-59.88212568,-215.2837448,3.688042585
+293,-75.16079292,-47.10523005,-72.33869735,7.966642163
+293,54.1798167,-21.12720651,-50.60676129,6.097459329
+294,-80.78132388,-73.57508218,-138.4810135,5.569575919
+296,88.8734675,-97.92722827,-169.2196164,8.181004159
+296,66.31287987,-135.6997369,-42.75815989,8.824039277
+298,-109.1802026,70.15936218,-107.6228042,8.391787919
+300,-143.0264631,-23.42697971,-178.5216354,3.431283808
+300,-126.8884017,-63.73510063,-197.045997,4.458681116
+300,-152.5091001,39.24279023,-264.9237449,4.779476584
+300,-148.8501076,-46.2823898,-263.4666085,4.298602389
+300,92.34849452,-28.14501624,-98.30724966,4.308746964
+300,118.3886326,-42.68235292,-247.8789499,4.207361086
+300,122.7403079,-3.364329503,-222.3942635,3.341564099
+300,45.14208761,52.2404132,-262.7505741,3.934638255
+300,7.723810414,-21.74870974,-89.81531988,3.744971475
+301,-54.06467496,63.55851124,-170.4688534,15.58144665
+301,-14.59718229,21.69665563,-82.20115147,8.256573426
+301,-110.5195873,13.24881288,-109.2784245,7.086777345
+301,31.29063088,57.77039933,-115.2752891,6.989971578
+302,83.03445343,88.63298054,-232.5065737,5.509268361
+304,-82.98918511,8.840855446,-85.89186517,8.604619037
+305,-83.15808281,-21.67899694,-97.00437642,18.7832325
+309,41.69536625,78.36878482,-127.8408681,5.235615798
+309,15.42130565,59.032951,-209.1954365,5.012771482
+310,-142.3151977,-174.2206828,788.1709415,5.789332994
+310,-130.8896371,-160.5028157,851.7759097,13.16123654
+310,-72.30182365,-283.8343361,850.6550314,5.520606059
+310,-49.26664508,-129.4859131,995.4654562,5.264434857
+310,-42.78758381,-122.6339512,988.0600257,5.896251459
+311,57.42043777,33.20420122,-61.85022853,13.81977981
+312,99.82868773,-146.1245536,-169.5334558,18.82522399
+313,92.68685919,43.57438553,-197.5473589,4.631274716
+313,116.8170346,-12.84537683,-193.306,4.2912149
+316,37.79855693,3.300009869,-41.39558427,14.13656827
+316,36.72219758,43.30048703,-25.14203011,6.259110412
+316,28.63381923,39.2872431,-22.76116367,4.389292516
+317,84.69521504,-95.11232169,-214.6123866,5.233283378
+317,-69.81151619,-69.68184275,-166.6322555,12.6270362
+317,75.71266555,12.58298968,-135.2999907,9.90073721
+318,67.24659457,-122.5524971,-155.5200459,20.41212558
+319,138.6417422,-118.7654544,-60.25410033,7.748454694
+319,145.6040538,-138.2558392,-13.4247001,5.071226824
+320,-98.0171699,-167.4527522,-188.9153442,4.392206805
+321,-74.87296853,35.11080854,-36.54442722,16.2317489
+321,-2.839756137,15.49133911,-42.88411974,11.0165788
+322,-8.993304035,40.54099463,-99.81467502,13.53288259
+322,98.19037939,37.78561001,-70.46713787,14.88143912
+322,-75.66575168,-51.48553141,-93.67729466,10.20083329
+326,33.61792724,-158.8860009,-129.4362152,16.02309072
+328,51.99987168,155.9191741,-554.1126447,8.793209067
+328,47.05520894,170.3943031,-527.5470707,19.84919656
+328,-64.76411531,222.4275025,-520.0442896,10.07288389
+329,68.29342162,71.32670944,-224.2446094,9.002203924
+330,-51.53790763,20.10350979,-85.16298794,4.515921778
+330,-61.83942051,-49.49988002,-178.135775,8.196011407
+332,54.57771668,137.2790888,-626.5921144,13.96263215
+332,109.4341558,229.6163407,-722.0838667,6.401625027
+332,96.37514949,213.0800475,-613.5363606,4.784886899
+333,115.3674027,-179.8695338,-281.6307649,10.63786384
+334,70.30866198,-48.69738576,-147.2003939,7.862425517
+334,114.9945322,36.94296309,-143.6292513,7.841667885
+334,-42.47036236,9.63938615,-67.76005548,11.16379761
+335,82.56241585,-80.96717899,-282.9247385,6.709234609
+335,131.4562868,-162.3474849,-273.1433425,5.275112281
+335,-114.3661632,-92.46651501,-245.4278184,5.860880895
+335,-39.56900888,-71.945242,-218.7775309,6.364695594
+335,-93.71921035,-88.23701668,-211.0024986,4.276776035
+335,-64.9992958,-71.02785858,-185.1208959,7.28852581
+337,-100.8609071,15.28935029,-182.4603409,4.991628467
+338,78.46553368,44.03628787,-86.86858612,5.696771445
+338,96.27646513,-23.55686252,-107.3733613,7.477744916
+338,72.19052901,33.77282956,-115.4497687,6.569503668
+338,63.78794006,-77.60063281,-143.2981373,4.983856442
+338,87.57932392,9.783753119,-100.9324878,9.088191083
+338,-86.83903189,51.57119596,-143.7114972,5.181246583
+339,-24.80602777,185.3534746,-545.8419781,4.355305398
+340,-39.61237465,146.7966702,-538.8806413,4.803859114
+340,-31.09781851,222.3105282,-512.3187294,6.773419875
+343,-86.68832064,-17.11866797,-52.87589103,3.661014906
+343,-89.52725087,-5.104797566,-81.96650621,3.93841182
+344,141.3149273,23.48811579,-242.6787116,6.375976946
+344,144.7977422,62.86369442,-241.1731829,5.305254374
+344,86.35325899,114.6358836,-175.477931,5.961135993
+344,-44.38911733,21.65032772,-36.19094841,6.012013105
+345,-81.21264213,38.50543905,-161.7782189,4.512190166
+345,112.2326686,9.722890567,-197.4920729,3.899770457
+345,76.4070202,7.959447114,-142.9888983,4.096360477
+346,-118.7456191,124.8523546,-568.68286,4.129168997
+347,-44.58942915,56.04434567,-51.61694575,19.91668687
+348,-115.6455979,-38.82732218,-109.6419395,5.738267951
+348,96.88732872,1.546082872,-74.21168209,5.063187041
+349,-65.48553737,197.2581037,-468.5690163,11.10051888
+349,-61.37799447,223.9639647,-633.847977,4.813145858
+350,147.9184452,-139.5398999,-289.3042952,5.371554924
+350,-87.43359068,-127.5413444,-262.5572502,4.82415072
+352,-69.25132002,17.49622889,-201.3042433,10.37870953
+353,123.0244827,85.5951695,-215.1788956,12.13515303
+353,96.41325044,92.61357881,-224.1152532,7.879370273
+353,127.5885954,44.77026048,-188.8742426,6.436398619
+353,71.66050173,94.49446209,-180.8208013,5.63626438
+353,-7.542193327,60.29166866,-240.9495399,6.01136994
+353,-33.96725483,114.1284149,-195.0651902,7.747960481
+353,-49.51411518,-13.58231496,-136.2125638,8.244882361
+353,66.14617331,36.39801261,-72.80318185,9.698623364
+353,79.179807,73.32770576,-167.728431,6.102801475
+354,-102.3832256,-96.39522474,-138.8622759,25.41540526
+354,52.60612067,51.0756965,-206.5,4.960423434
+355,118.3234759,20.24704104,-155.2786841,13.84883567
+355,99.32939332,66.55314921,-92.09688887,6.673547135
+357,-84.393952,246.9323285,-508.1886279,23.57156231
+358,75.47571744,71.69373908,-97.73229784,7.389997194
+358,56.58729736,69.68454035,-109.1245027,9.025365556
+360,-64.40112214,7.841496444,-75.95221202,10.7221465
+360,51.29471463,12.62769201,-44.86446771,4.761221031
+364,-55.52821414,245.4376219,-758.1325898,13.84309944
+364,-116.4604191,230.1689873,-747.8614134,5.388364876
+364,12.73732548,216.6918398,-790.0747986,6.868316403
+364,-139.713455,186.4162971,-789.1416745,8.743609647
+365,101.948344,-58.63218351,-205.2437531,5.619534834
+365,48.57179203,118.4387376,-249.4687169,6.548067679
+365,75.63291901,111.2621798,-182.1446944,6.279521551
+366,38.17558461,76.65811776,-217.8804577,13.20481203
+366,111.5397212,26.17387565,-216.2738565,4.438915742
+366,97.6759868,59.95440744,-182.4642658,4.586830375
+366,88.64532883,37.12480761,-129.2822334,5.315639734
+367,28.82164325,-67.50284479,-119.4939135,14.74449324
+367,86.34284609,-24.24169612,-116.2560573,6.542124227
+368,-88.87929578,252.9672218,-542.2144094,9.584711922
+369,-91.77607345,193.6749754,-636.6738832,15.67293211
+370,89.75123428,33.49305253,-150.4590146,10.52433762
+370,76.97808959,61.77172767,-133.750295,7.131301409
+372,49.69416659,104.6858466,-297.5292319,5.244468721
+373,-20.26058318,66.58938539,-206.2408307,7.789972805
+374,-90.49973305,-228.203463,-347.1502138,4.83748734
+374,-149.0749233,-156.3745612,-422.1191067,6.587261619
+374,144.3496682,-136.3511163,-435.821845,5.973944221
+375,-79.51333218,120.4823722,-68.3844107,6.313681857
+376,72.88274978,-1.28143171,-56.52006584,17.52596027
+377,-87.39262251,181.7454561,-508.5616381,13.18081087
+378,103.4901351,19.02440919,-227.2106621,9.286445444
+378,97.32696572,38.24556909,-208.1462513,5.963386128
+378,-31.01740011,-25.19581883,-196.2932789,6.2309343
+379,120.4418988,44.41861238,-245.4755968,4.900924695
+380,-90.00339918,-218.9498337,-205.0745819,4.65186366
+380,-86.57914744,-204.7481346,-203.6073358,6.385959004
+380,-68.26080546,-69.21122599,-196.1228776,7.186704876
+380,-73.17249303,-55.92625797,-183.7214311,14.79788128
+380,-73.66370598,-215.809667,-183.9092361,6.489388614
+383,-108.0795881,-70.76676061,-138.1757851,4.341588419
+383,-113.1622011,35.11715185,-166.5081249,4.635624615
+383,-100.2598962,-60.33797935,-135.0709524,3.923712299
+386,-103.1975366,-156.0826648,-199.8792945,6.23861912
+386,-75.85511002,-144.2211893,-61.73576306,4.137877518
+387,97.95579219,28.73484404,-133.4079455,12.1674054
+387,95.35113888,50.21460247,-139.266673,12.07617755
+388,-93.80070346,-42.0638866,-161.4495149,4.402510304
+389,67.29092485,-2.511403926,-97.67385656,7.9202838
+389,52.2639469,1.497597,-106.7882515,4.141481922
+389,-95.13594331,66.11688471,-155.0085322,5.592105263
+394,-61.58176887,203.663079,-406.8238622,10.02702167
+395,-64.82348424,-60.70896428,-192.062522,7.985106486
+396,-103.0650847,-201.9728639,-199.259719,7.824906419
+396,-54.51336914,-97.31184902,-302.9102068,5.728868072
+396,-78.35817417,-112.2362811,-207.9264479,5.0659595
+397,-67.1632622,34.25872475,-138.0189691,5.957179253
+400,64.68198292,32.10248901,-236.2047709,11.60251126
+402,-59.75176891,-45.51209719,-84.77197151,5.52981148
+403,-47.90112947,-52.76024068,-155.8593999,5.498575682
+405,-58.14574208,-55.41029389,-195.8649752,6.006388591
+408,-87.67051321,26.78212237,-68.95236036,5.362783598
+409,67.94312597,-57.5603859,-192.0483809,5.143368003
+409,-89.03608095,-4.521104786,-184.3910257,5.494770376
+409,-50.06071754,84.28251833,-182.0021641,7.016006655
+409,52.03768945,-57.49443854,-179.1694878,6.197677084
+409,-55.35427856,-21.73921101,-170.024255,6.567796504
+409,55.67723378,85.91442717,-184.7025172,5.810350051
+409,45.20399101,82.20492377,-187.3730159,6.104617991
+409,67.70370235,-42.03608191,-177.5220588,4.898202157
+411,-67.89250682,66.62625425,-201.7299033,6.232717756
+411,78.57938299,-32.83961731,-117.1172356,5.981259208
+412,37.2907856,-153.930576,-230.4874106,8.361662881
+413,-124.4281777,127.7209789,1633.223987,5.253525386
+414,31.3515371,49.9935034,-93.09019002,9.953169615
+414,84.46996514,54.58091128,-216.1892685,4.257333181
+415,-70.05203824,-177.2863673,-196.0178473,4.481196844
+415,-105.4904536,-195.789589,-231.9827617,7.340286975
+416,-112.2957484,97.35768343,-324.5095395,10.43124188
+417,36.10138756,56.74686,-225.4606863,15.27003429
+417,88.04700244,82.06805138,-235.1776874,9.514315903
+417,76.8032595,80.64710662,-206.0164263,8.220380612
+417,45.57006602,34.24015941,-140.1768512,12.99686424
+417,62.56152545,73.24041758,-255.6159586,12.13959395
+418,-97.40113449,23.34590944,-151.9773605,7.370224529
+418,34.04035793,29.47635335,-156.4414006,6.018626532
+419,74.06556161,-121.2537719,-208.5776702,6.429381085
+420,-102.5054319,184.7539324,-376.0209821,5.217135106
+421,-53.48738674,-155.8038863,-244.9570362,5.694304171
+422,-54.53295263,-122.3417894,-106.8530672,12.06823325
+423,132.7235076,-2.482715594,-178.7296901,5.676359559
+425,104.3487739,-50.6450938,-178.7102944,5.696507379
+428,85.10312764,68.1231479,1552.672487,6.858527982
+430,102.2399542,65.22379138,1561.838456,3.973281304
+430,79.74714343,43.96384249,1624.371493,4.297245295
+431,130.8516193,88.73648159,-200.0790996,6.009066896
+432,146.8476333,-9.053466102,-165.6777809,5.784239296
+432,-101.1317473,-66.59775552,-149.2552797,6.605182062
+432,-113.1069633,-65.53102431,-141.3337001,3.994313797
+433,-77.92733327,201.3950992,-334.2187716,4.686873877
+433,30.32154661,113.8050094,-401.1255093,12.65708157
+434,93.40756606,32.61451529,-183.9276734,6.405074711
+437,-55.33524393,103.8208322,-99.0727983,4.443753341
+438,29.40142613,79.93102755,-273.0968803,16.77602203
+438,67.01986114,2.845989356,-85.92605423,12.46806721
+439,61.14957634,65.36834984,-282.8838048,8.815802572
+439,-82.50977278,75.76669562,-284.3027222,6.765042258
+439,78.1449453,84.69417166,-181.0381686,8.279651627
+439,129.6606906,32.39491492,-174.1825371,11.36963426
+440,102.5994972,-85.18892956,-274.7995891,5.384158274
+440,102.8516419,-142.9349464,-264.1177375,4.756333837
+440,93.17781319,-61.86571862,-251.1174529,5.118324575
+440,-108.2741578,-128.0277449,-247.6879925,7.070646904
+441,-99.67287454,38.01094057,-117.1044624,4.683570528
+441,145.0481102,33.85318709,-189.8031919,6.242190906
+441,123.6737499,65.76589059,-210.8132276,10.83118822
+442,100.0021827,22.00611876,-147.0757546,8.871621958
+442,-55.31574942,4.042374673,-154.7552924,5.970538617
+442,-25.40860122,136.715217,-181.6943198,11.08601237
+442,127.2115066,44.79847847,-164.7894133,7.72427841
+442,120.2208995,50.312055,-132.1372108,5.251592099
+442,101.082909,-3.953008029,-180.4023007,9.404294354
+444,73.76386971,56.33474997,-111.8408463,4.084912815
+445,-82.01433803,-28.01109961,-153.9073895,10.06186005
+446,-83.90348039,-43.19714842,-275.3149289,14.81279634
+447,-118.1529007,10.0091412,-172.2271819,7.083745614
+448,60.16096443,67.20210777,-97.95107479,19.57555466
+449,-85.06548421,81.6029288,-149.5488028,5.285669845
+451,-107.2159607,-18.51266964,-209.7539105,6.002516297
+451,61.32976859,84.76491799,-250.9065563,5.129855377
+454,78.91931222,28.0701114,-30.64770351,6.145856048
+454,-112.0234972,69.97418001,-99.2558482,4.341383521
+454,-81.57264551,-57.20275617,-167.9608443,4.730361001
+456,-58.69016149,-46.43839771,1449.3662,17.60680854
+456,-36.28894981,37.1796656,1549.254705,12.31597935
+457,76.68553038,79.72250117,-100.1052284,5.978370835
+457,-106.4518389,79.48717995,-194.2562157,3.586891724
+459,-86.96072327,-223.9393033,-156.5318361,5.580524027
+459,94.79861345,-131.0465533,-139.7058976,6.073504253
+461,-115.3501501,-13.63731068,-174.0566414,12.98553245
+463,-11.68147261,69.32037685,-177.9755523,5.146058962
+463,-14.23272252,54.11225209,-168.7037196,18.02111617
+463,-47.10027725,55.21237511,-132.715981,13.80566396
+463,-43.72223094,80.4630221,-116.2138052,8.896326902
+464,-42.79341777,-131.4626408,-226.1803103,12.65179825
+464,86.76513695,-104.194718,-197.5664809,5.436792782
+465,-92.27396082,49.15940214,-179.9056886,6.358950284
+465,102.2669667,60.33818513,-151.4941817,5.520478941
+466,63.26966891,77.36318965,-225.9292676,13.44804609
+466,95.0892826,1.698275943,-126.7249875,4.501806204
+468,-41.61771193,178.4096622,-381.2501196,19.310152
+468,-53.43332809,148.1412784,-393.7043538,4.013764282
+468,-40.57117818,122.6396589,-434.5711893,5.744030221
+468,110.9646084,136.259879,-527.2449875,4.983754092
+468,-49.10667981,117.2006652,-438.8990091,3.589491744
+469,-59.76229837,-62.2617989,-167.156639,4.793159505
+470,-29.1228645,48.5569787,-85.50543462,10.72670328
+472,-56.22044118,-34.51721529,-144.2330617,4.958169738
+472,-62.78408473,-54.35912078,-153.7498201,6.179309944
+472,-56.69302662,-71.39766503,-160.153874,6.024061049
+474,21.13605804,3.015375203,-90.46574675,3.968197931
+475,-101.395296,-125.8650982,-179.2955087,4.570090698
+475,-77.84509313,-185.9564699,-134.911108,3.805906302
+476,36.99117198,75.96897009,-211.922723,7.968882541
+476,-55.69319085,73.99821874,-147.3502844,14.67752407
+478,-96.83638558,24.05696088,-138.4551231,5.406806871
+478,-50.68978766,45.876185,-110.4343429,5.934589046
+478,-72.81004385,-35.14068792,-78.38709823,5.713817831
+480,88.51247939,-68.10352403,-147.9907896,4.720379813
+480,-80.45493331,-84.32187708,-128.7269511,6.111922058
+480,57.60716664,-75.94085727,-109.5389192,7.664341312
+480,84.50307774,-76.27875698,-89.27114991,6.705330851
+480,79.6430395,-114.6833702,-74.70024737,4.858789829
+482,0.378580731,213.6507752,-676.932069,5.866867348
+482,-69.1757411,218.0526254,-668.5012726,4.441200069
+482,81.09750567,241.7018527,-701.3822918,4.227905054
+483,-96.92511861,-19.80447862,-120.1001986,10.60627713
+484,116.3125797,12.94951993,-80.41107871,4.554576075
+487,-85.25444741,-46.79571211,-180.6569421,6.856554178
+487,-90.23807193,-88.54741894,-174.9446668,4.746983627
+487,24.60583341,-33.45402892,-45.67999081,4.680676552
+488,-65.84352891,-77.23814671,354.4514823,4.406865675
+488,-71.45458891,-176.2479812,241.8137726,7.977820653
+488,-97.8083916,-183.2310149,249.2611219,4.198740236
+488,-93.68123544,-176.0318756,213.2126387,23.93362973
+489,73.79496797,69.55764009,-35.17353835,8.158102396
+492,-116.1875069,0.827026319,-238.0362876,5.834911249
+493,-12.41585622,-184.5111396,867.1793966,12.16970693
+493,-24.11055443,-171.5345888,864.1143948,5.54930965
+493,-89.80382595,-68.12701296,873.8383847,5.536440222
+495,-94.17099656,60.22888982,-185.1525725,7.636326684
+496,101.8010914,-28.53858261,-173.2606127,5.582216627
+497,-49.72758728,-19.98555378,-151.9287579,14.31390685
+497,-71.7826853,-64.17026387,-210.6358489,8.22221772
+497,114.0663418,-39.7958665,-161.1772179,4.771826524
+499,71.24730999,68.44187934,-190.2289952,8.489837273
+500,-108.438374,-118.8944651,-221.9638299,10.05662598
+501,123.637574,-5.081129141,-262.4648206,20.38922514
+502,36.84866907,178.6334519,-603.1030289,5.028864971
+503,-36.64395514,-76.5761924,-155.6091206,15.28264973
+503,107.3014973,-1.66826224,-189.204955,20.03584717
+503,129.1442701,35.49501731,-229.6640754,22.13533119
+504,-45.80479316,59.89230782,-200.9927893,8.766657397
+504,-88.56419765,20.20911916,-103.7426809,7.076676777
+506,96.78026471,1.565748925,-113.1028372,22.03891888
+507,-48.52221096,45.38208006,-90.22368433,22.88079244
+508,-101.4017843,87.31094814,-230.908114,6.044864617
+509,102.2324301,210.5837195,-614.3178454,4.335976969
+510,-77.6685505,156.5915805,-517.9735625,6.373118453
+510,-72.80446275,223.427845,-567.1713376,6.031697835
+511,87.89218568,-56.95129309,-142.9535988,4.988818646
+511,-97.01461145,-21.57207523,-127.9731352,14.21146202
+511,-29.74141401,-18.46166759,-134.2459518,17.98864725
+512,-98.39887472,-257.6239438,-242.1180244,5.048067067
+512,-48.06616769,-258.0504359,-250.544875,8.413884666
+512,-90.94045378,-230.2193214,-217.071482,7.663782425
+512,120.8151682,-117.7561585,-258.7667719,6.920897477
+512,-114.4516276,-91.13719415,-264.111843,5.964079886
+513,-75.51553848,-45.34884762,-144.4902038,7.593735846
+513,33.0178907,94.39493036,-251.7982184,8.328291294
+515,-87.72559112,172.6043391,-580.1726871,5.155662025
+515,-60.31452861,135.3053658,-566.8624414,4.520944354
+517,-67.45950309,-247.7442112,-211.0953396,7.744221728
+517,-97.69087642,-134.0680536,-187.0948829,6.690036478
+518,69.52914115,87.03615287,-149.1901128,10.82451529
+519,-57.0819205,-85.17233126,-214.5551686,5.070932612
+519,-48.22664898,-66.08106226,-209.0373634,4.717405126
+520,76.95201463,-27.48605744,-148.58781,5.863401006
+521,106.9705181,8.301864146,-139.5403359,16.10237553
+522,-131.9599469,55.69961281,-165.2127172,6.618630161
+524,51.48901046,9.855025846,-86.83518484,14.86094152
+526,-73.72958121,-50.52444839,-259.1407657,4.533837123
+526,-73.96568646,-92.44533909,-238.6529412,7.185957941
+526,-52.54525764,-195.1320838,-180.130679,8.436595788
+526,-85.9411151,-169.2745879,-128.3546076,7.595614881
+526,32.58870589,-102.4937764,-88.46395383,5.642186103
+526,-73.19462067,-102.8061689,-166.8263298,6.172638207
+526,106.6949197,-126.2271369,-246.3140429,22.77961842
+527,-72.12347451,7.797144105,-217.0274902,6.844315185
+527,5.688584989,77.51244888,-142.6580166,5.905235821
+527,14.6814816,64.49124539,-233.5115248,5.597494358
+529,110.1355596,-32.0169515,-241.1046505,6.005399015
+531,-88.49125714,4.69078919,-184.9336769,18.50978255
+532,82.49968,-81.76246933,-162.3132715,4.206700455
+532,91.76868348,32.4243149,-101.9035024,5.58156934
+533,101.0640749,-2.909610731,-129.7329156,6.417805328
+533,98.17857282,40.23143915,-147.6875423,6.351836743
+533,111.8026601,34.3791455,-156.3357581,6.898836492
+533,54.86650139,83.42134104,-200.5208054,15.9976197
+534,79.24095142,105.0621099,-170.1267748,5.838910273
+538,-57.93049681,-30.77966437,-83.41758578,5.73592519
+538,-66.07883697,27.44178912,-61.40408623,6.862125594
+538,46.81849127,-6.947360373,-20.34015546,4.023705654
+539,-90.94204444,9.422642589,-72.51868585,22.22543938
+542,-66.56658517,-40.61335572,-118.4928899,7.53039924
+543,102.2377292,65.32842988,-240.6955559,18.210145
+543,22.53616818,34.72145001,-117.4375995,10.33971307
+543,60.18947724,-45.04675978,-112.6427797,8.349225392
+543,67.82725575,85.37992457,-109.7467238,32.27003025
+543,114.1058249,-11.85681073,-165.6215278,4.915612527
+544,-23.97628,66.98028611,1569.020052,5.40759858
+544,-107.6908186,82.29497289,1432.633036,5.611908232
+544,146.5013001,33.33503366,1433.047346,4.639346679
+545,-59.39053533,91.29824683,-217.315565,18.99864751
+545,-65.43453788,68.62896143,-282.4272547,13.55294288
+545,80.32564185,58.99865099,-150.4842755,12.71396134
+545,92.70661624,19.69810556,-194.2689681,8.80965529
+545,71.01942171,16.25754185,-196.9970104,6.877252867
+548,129.4752815,-51.57101338,-251.9485797,5.529020275
+550,116.7588076,-180.8050991,-234.5537632,5.106009516
+550,-83.62032739,-95.87788076,-221.5685425,6.216601241
+550,-92.89107114,-208.5061595,-203.2724929,4.251282657
+550,76.66626608,-163.8716684,-147.2499084,15.6929733
+551,44.32326395,82.57803325,-189.3255283,5.56275007
+553,135.3036242,-21.79208926,-239.4086072,4.543071313
+554,-62.19588874,56.10498787,-94.82411775,5.982909574
+555,-68.00720196,-41.02746294,-172.1175757,5.247278653
+555,-86.83682341,44.88428152,-150.5213276,8.103288228
+556,48.93160782,-57.64898774,-73.99981349,5.743023818
+556,91.74344115,1.489122847,-109.3375922,4.950660035
+556,-64.32373023,56.85721717,-168.4427428,6.331569947
+556,-130.2047538,27.56977296,-210.2722058,9.503203598
+557,-84.56144675,53.32378035,-281.9974642,5.556944532
+557,120.7849264,26.79966924,-282.3975687,7.903510371
+557,100.7686809,54.38122979,-256.9953278,5.722280115
+558,-131.3987948,-2.758456139,-221.4306053,5.6734543
+558,60.46365697,6.684682456,-166.2635713,6.275342115
+559,-46.90144291,75.75702229,-160.6226978,7.000523906
+559,-70.85118947,43.23273855,-161.9030791,5.103331958
+559,-65.85355844,81.31080175,-179.9458889,4.09125367
+559,-78.60873551,83.60316733,-180.3313412,3.604122074
+559,-68.57907771,88.63420627,-190.8726177,4.36498067
+560,74.06988329,38.35306684,-64.55323564,4.620478005
+560,92.75491946,28.68047227,-68.42174667,14.01055468
+562,-68.98527379,59.65236221,-93.7862976,12.23861568
+562,69.39410493,2.301055592,-116.9214528,10.15451033
+565,-81.4227151,-72.28037593,-175.2840689,7.803510446
+565,33.10479474,-63.11643351,-108.7255712,10.7593487
+566,-48.25336944,122.9531915,-662.8189689,4.741226698
+566,-79.34409697,174.995213,-675.2716339,9.54755631
+567,50.97022755,-34.22691743,-145.0871207,9.854691375
+567,107.2310959,38.93370431,-202.7540175,5.698508138
+568,-102.6786393,-60.02526548,47.31904974,6.309861737
+568,-128.9519043,51.49699246,-46.08862011,5.12610172
+569,96.62595381,-46.15482266,-88.22943221,6.326436035
+569,-118.326081,-37.39744532,-110.3530583,4.088340903
+569,-72.28799048,-77.48196772,-160.4862542,4.087102079
+569,-57.72551821,73.77949357,-147.4155797,11.80179732
+569,-72.58061805,3.189654663,-124.7859175,7.740811844
+570,76.92845221,42.9591148,-156.1113403,4.359847311
+570,-48.19484987,85.6472109,-106.9277616,6.223836401
+570,-61.79005197,85.7037051,-88.95044821,4.880407071
+570,31.99820076,87.0398605,-87.30499286,5.264823454
+570,69.06378759,-5.20922866,-122.7216281,3.588905452
+571,118.8935973,9.543387329,-223.3917754,22.30485311
+571,-32.57589084,-38.49990256,-195.9028979,9.65159512
+572,-68.44093973,-157.1137025,-176.1858824,4.805890569
+572,-55.10711143,-92.46668464,-105.1251227,6.821386617
+573,-77.1815686,-56.67932785,-210.12595,3.844582048
+573,100.1064082,4.113763028,-93.59102919,4.375706691
+574,-64.08984827,-185.1943695,-176.461318,3.556818181
+574,-112.5257962,-147.0691547,-279.5736221,6.661399227
+578,91.67018342,-140.4872171,1157.979081,13.0575593
+578,73.32391758,-154.0753119,1175.026682,12.76400579
+578,61.57360432,-112.1197753,1206.626262,8.68806614
+579,85.1785161,-36.78139636,-100.6408476,8.623614727
+581,94.08411483,8.592369179,-226.0784745,5.320080577
+581,91.171059,11.67926171,-221.9540872,4.509994543
+582,-35.86499577,50.0903772,-54.97785519,11.73040225
+584,90.69412437,136.8807468,1521.030798,5.060034849
+587,-134.3906237,-122.7636416,-297.6611428,7.068103093
+588,-61.93533913,226.7878603,-379.0557742,6.972916889
+588,22.14091595,196.0980962,-367.3614119,9.253917448
+589,-128.7512557,-1.511218785,-213.3437987,5.62818632
+595,101.2451127,15.80942106,-105.5725817,16.09508736
+595,117.1530633,-1.520032995,-208.7261177,21.67749437
+596,-75.58452659,43.10980417,-128.326338,7.850328152
+601,-46.88603145,-71.47201601,-204.7362163,5.253505195
+601,-85.90557458,-179.9071501,-108.8742678,5.100020792
+602,48.84233801,-79.99347491,-170.1226167,7.747145031
+603,-44.74552511,15.74507375,-199.2057467,11.06629748
+605,108.3539126,17.6636324,-144.3487942,7.19927326
+605,-96.74440568,37.57394502,-138.1604297,9.008401966
+605,81.25238955,-61.95603652,-102.7392007,4.624706443
+605,64.42239176,10.39856954,-97.91300482,6.180360378
+605,87.84093673,-9.774362874,-73.52174071,4.481934217
+605,-61.41380792,86.92191873,-68.29510047,8.748557314
+605,-89.72409213,4.989814421,-36.10094622,4.393756108
+606,-43.17549976,-70.66475672,-149.5314353,8.488955168
+606,-111.5859962,-21.64957873,-70.20646602,5.685267589
+606,-93.51330673,11.06618299,-126.3944134,5.234851716
+607,-46.84173683,58.34921221,-64.06849523,8.364989395
+610,-89.41960826,230.4681484,-614.3390574,7.59997723
+612,-6.607170093,22.55937329,-143.7929641,9.48489034
+612,116.8024039,-1.291850522,-197.5054168,4.666322736
+612,119.2088976,-11.4328236,-208.2932951,6.853377495
+612,111.5336493,-37.25625083,-238.8281758,5.772283337
+612,95.99601184,-23.33441995,-157.7220192,4.835148932
+613,94.35547105,91.59711801,-85.60911893,4.473572199
+613,20.84754253,147.7875736,-123.7256197,4.945821582
+613,102.312989,110.4620141,-170.2480634,6.418972326
+614,-96.15880098,50.98702071,-126.4487451,10.32149081
+614,-129.5582207,43.95116739,-164.9900987,10.417941
+614,-54.40303309,81.75967211,-286.5417517,15.71097733
+615,68.05574564,43.7031034,-266.0215516,12.68580657
+616,-104.7330571,-65.28037827,-153.0965685,5.654138498
+618,-104.132632,5.561806071,-43.86310901,13.14006008
+620,-47.98966389,-118.8036156,-82.10624424,6.853098388
+622,-78.34099522,229.6995557,-700.4896349,4.015559137
+622,-94.11576971,212.0770162,-721.5469281,4.385767296
+623,49.76140034,-30.97057504,-40.7778355,5.937590395
+624,55.84381658,87.20226025,-175.8774794,4.034133192
+627,-97.41069879,-44.65572813,-143.8867224,24.66335961
+627,41.19376183,-3.596828721,-11.48987867,9.067255434
+628,111.3562508,-106.6054694,-118.862537,11.29624596
+629,-87.92743528,-49.5343381,-117.0008151,9.443896197
+632,125.1264993,22.05896161,-185.8029252,4.936242591
+632,-40.79954744,79.7815833,-160.1080585,5.433793389
+633,-77.02533313,89.93861809,-135.120507,5.183339807
+635,-20.72433589,-82.43422239,-163.5191536,9.991058045
+636,74.13268405,-26.75317521,-252.6553875,10.03917434
+636,-47.21141318,95.09026184,-179.9203418,12.79644145
+637,-78.55235498,24.91578897,-107.3639625,7.165672419
+638,72.1887603,-14.4688642,-195.2387769,22.46928325
+638,74.72764672,30.75813083,-101.3115905,18.86783511
+639,82.32330622,-183.4399074,-199.7152718,4.084248678
+640,-50.16716421,27.87502068,-59.55902456,5.521988183
+641,-118.0512328,94.75414104,-230.190551,4.560710413
+642,97.83677666,55.50902909,-280.9785357,21.08245746
+642,88.68803313,29.52753243,-267.9721837,8.515646762
+643,-57.16455992,44.51132063,-79.73793688,6.614419285
+643,-80.95533246,-74.33680027,-115.0576615,5.104384596
+644,94.97968016,77.58891384,-162.3511214,5.134733017
+644,93.02994736,76.85220572,-180.3229252,6.306448592
+645,-107.0930177,-230.4358408,-196.9335875,3.90241061
+645,-34.21742242,-258.2050698,-180.5932222,8.714126601
+645,-89.74386627,-177.920042,-171.969291,11.05222629
+645,81.06879582,-250.9442408,-166.747044,9.330163033
+646,-87.6116254,-12.62484473,-163.8559956,9.82174492
+646,142.588728,-5.403468458,-299.2211503,5.07904476
+646,-35.50220052,12.42447242,-98.52928857,5.208074501
+648,-75.22199506,62.49234348,-96.3478276,12.6058106
+648,-48.04666893,85.21928222,-143.2366224,4.745975018
+650,-50.86292739,-91.99602194,-156.3356188,9.407091622
+650,-13.65835546,-135.5047895,-97.68078459,6.305697229
+650,-45.80083441,-101.6518106,-90.27642107,5.323697876
+650,81.35608846,-134.6072395,-77.74723215,7.702745337
+650,-32.95652305,-165.0205503,-80.42038104,4.225740939
+650,27.35574333,-113.1712109,-118.7382011,6.875805854
+652,94.69277052,-58.75126934,-223.1832419,5.902097585
+652,92.33199711,0.471155965,-196.1703197,11.4077692
+652,76.37260492,-58.7146568,-188.3180962,6.762379039
+652,38.18494377,-70.85731384,-177.4034718,7.013205598
+652,73.40337941,-79.17103932,-160.465872,7.382823191
+652,54.10098991,-74.66241303,-158.289718,6.162501209
+652,47.3980366,-92.91586123,-157.6125367,4.696704052
+652,-94.14005815,-66.6427403,-243.48921,5.375765996
+652,-72.47324637,52.77800062,-212.0353733,5.116058049
+653,-91.50114978,-5.251185287,-138.9674206,5.41336635
+655,29.80896453,60.46795255,-278.3676965,6.955440317
+655,36.07972135,-29.73608262,-89.48053564,23.04344837
+656,-90.91776955,82.31102136,-186.4472527,6.724954348
+659,-52.41930738,-24.7935206,-176.1642111,16.82893945
+663,-83.91769065,47.09117513,-181.283014,6.862828144
+663,-88.46186388,18.95338468,-176.0384633,4.838097863
+663,-1.495127425,44.84438957,-163.8288849,4.87074364
+663,-12.64801202,100.0271132,-125.3106987,5.264828408
+663,-37.95117393,-30.07284828,-111.6084477,7.736403192
+664,-36.55628288,94.95448429,-231.0861394,8.208342207
+667,-120.8495868,38.33931617,-214.8832613,3.8850462
+670,-90.57045037,207.9808255,-397.6269191,12.57054118
+670,-105.1725776,139.3306893,-448.4343057,7.178922623
+670,-113.0089772,127.6639141,-453.0456329,8.244643239
+674,74.90098389,49.24864607,-272.2131935,6.906358753
+675,119.0033407,-77.2002687,-168.6785433,3.951407423
+676,-76.00397264,-74.92869851,-144.3113557,3.832603383
+677,87.92913193,-5.62348127,-78.69493667,10.26078692
+678,33.41175886,64.8927258,-40.57820167,4.341079966
+678,-90.27970946,74.93542164,-133.8851368,4.237778745
+679,-78.23081813,21.39196957,-185.9204699,11.84107821
+680,133.1840306,25.58478375,-208.4050921,4.12101305
+681,-117.3851233,45.19195728,-257.4459001,5.452780772
+681,-134.1902889,48.08074626,-239.5518182,4.163773675
+681,-132.5650132,18.96298014,-228.7955644,4.568161742
+681,103.1815309,47.86818853,-219.8350623,6.243459504
+681,85.25214188,74.58500169,-205.0377632,3.82131275
+681,-102.1574605,-46.84750906,-174.9138243,5.106805338
+683,108.1375346,-9.028290781,-127.6592922,9.566936036
+685,-59.55816545,9.14828959,-95.45329765,16.63502176
+686,-68.66002474,-222.4854341,721.576668,6.470686725
+688,-107.5159318,-106.6040007,-155.5003217,5.32434611
+690,-91.44763653,-161.6158227,-83.1478899,4.911932277
+691,-66.077863,-80.56168862,-170.6863395,4.889664292
+692,-88.20063783,63.04192832,-106.3064074,7.734742324
+695,41.21933645,-169.5888219,-188.6252342,4.528739349
+695,-92.43802134,-160.7622717,-127.003377,4.945112775
+697,-21.40817655,5.000621102,-43.01868987,5.992452195
+698,-36.77629406,-34.59533297,-60.9137866,6.217909816
+699,42.14750822,-93.64201295,-89.8178088,5.295457654
+700,-64.11832825,-4.887440096,-85.9024469,5.105120807
+703,16.89279224,206.0055517,-53.00858628,11.47644347
+703,-86.9332203,218.2319275,-221.6654195,9.693203437
+705,-82.10323524,-41.63735095,-207.2455405,5.087935069
+706,97.16800868,-79.94056414,-202.9715324,5.063233243
+707,122.1608996,-197.2499255,-159.4693446,12.95113108
+708,82.98012239,225.3061366,-584.6161159,17.15288922
+709,126.6383304,-51.84356121,-199.6021014,4.862136589
+709,-41.46961577,39.41958903,-171.6209897,7.121051509
+711,47.82112531,56.01070133,-73.06979386,6.439255223
+712,-88.08860961,207.7635084,-571.9349406,3.900928245
+713,109.4087162,6.639637027,-191.5459318,3.820577768
+715,-44.935479,-106.3779813,-148.9946026,12.02215382
+715,97.59537431,-97.23526941,-216.3795429,7.418028913
+715,33.2035765,-121.3308637,-109.7314672,4.525236758
+717,-97.07004047,-23.31208254,-166.0109699,10.80320051
+717,-136.5376416,47.45753694,-191.6392867,7.851521411
+718,-106.9061926,-134.471772,-187.213428,7.600976518
+719,-104.3323085,-130.4591242,-81.17828567,12.30437661
+720,-88.50801052,131.345573,-271.1059173,4.510288907
+720,46.50497117,229.8924044,-310.5933997,4.462472935
+723,52.95010295,21.62343136,230.6859795,11.17547004
+723,97.32393157,-33.77077028,128.8311577,4.514863772
+724,1.251885508,77.30842113,-146.9519795,5.330056155
+724,67.93904669,-29.64640439,-125.7321771,6.16795392
+725,-19.66337758,20.48820018,-21.31695749,6.330288195
+726,-94.45393926,29.01531686,-208.9912079,8.128059459
+727,89.71484404,72.84152648,-235.9893669,11.23154253
+730,103.4749192,-182.666071,-102.0404523,3.885893197
+734,-54.71035427,80.77610592,-176.7413443,5.920275846
+735,-152.3569324,-22.28584934,-274.372396,7.88580587
+735,-140.77731,-19.60100137,-205.6472092,6.256102138
+736,-103.1325112,-5.774672551,-206.3554703,27.07544345
+736,32.96069525,35.98248454,-176.7836812,16.92306528
+737,154.4288878,28.97499705,-196.9548398,5.193342015
+738,98.89687283,104.1862012,-208.7759854,8.085638726
+739,119.2087756,11.45037434,-165.0398624,26.83708074
+739,-37.9016173,55.02791191,-80.00260537,17.71872916
+740,48.68312155,-15.3562681,-80.56923419,22.78152704
+741,83.04181413,50.63250635,-155.5115559,7.915780715
+741,-113.6831711,-27.84528163,-82.73840622,12.4582541
+741,-111.201589,37.52576027,-67.13579078,15.39279188
+743,122.0139844,24.02512622,-225.7265261,5.490544909
+743,-88.81651763,-74.16058624,-217.1773728,4.522057979
+743,-101.0307142,-45.9959128,-151.0599558,3.297324878
+744,60.77506053,74.1239696,-214.7823466,25.23320204
+744,-85.42103886,25.26172136,-220.8338299,9.756615445
+744,-108.5275162,-38.82524711,-199.2073071,10.98914009
+745,98.89299547,51.3099692,-80.74183737,7.936007136
+746,100.4478992,-88.72756916,-171.2353199,7.805767837
+747,128.0673817,67.86393899,-90.45140764,11.64560862
+748,-95.03957237,63.78027309,-94.86346155,12.80135622
+748,55.37992901,-25.7577385,-70.43270211,14.62904955
+748,123.6022363,-8.037283428,-208.2595121,7.283782817
+749,113.911431,-36.97202364,-139.1067807,4.315291242
+749,-87.29823867,56.27165698,-112.2906343,5.965579845
+749,-42.90649318,-3.298740043,-115.1038593,5.090964239
+750,-48.64254924,100.9304096,-200.037037,4.890021449
+752,-28.41228581,68.09366695,-217.5060488,7.234065071
+752,-42.9563814,58.59938953,-185.6246292,5.897380231
+752,105.1933092,48.21925187,-129.5645198,6.131649732
+753,-77.77160404,-11.38994533,-58.0353619,16.72146339
+755,-113.5220772,-36.28177026,-185.2756636,6.999823116
+755,59.33099578,-24.99237386,-197.0399122,8.735774018
+757,-124.6694679,21.09709755,-169.6039762,6.731878569
+758,68.58568744,-67.75578772,-143.4967682,5.572904514
+758,-48.13074393,-63.7034127,-63.36622225,5.484694873
+759,71.57549333,73.92373635,-83.81039939,4.653858021
+760,112.2403927,-132.0813274,-179.2208201,10.1269398
+760,69.81421013,-130.6756074,-81.60242179,5.700892679
+762,-31.90828695,27.18117285,-170.1513701,10.16765351
+762,65.99742568,108.8944115,-168.7229948,7.918815315
+762,-126.4570776,46.47158404,-203.9176616,7.023509324
+762,103.1762058,62.99828473,-152.2623412,5.210020858
+763,71.20286623,48.41022668,-148.644687,4.968821175
+765,-25.81676365,22.03533828,-188.047378,22.23698113
+765,-22.96609737,32.46155666,-207.3871693,18.40907555
+766,-43.53528889,61.08229652,-176.67486,12.55350151
+767,-39.56968699,112.6564673,-173.7075034,20.88367551
+767,-59.91906947,-50.47767665,-171.9343744,6.009893707
+767,-12.14726809,80.91852167,-147.9105199,6.872010445
+767,79.1758748,56.23553805,-153.669653,8.222297439
+768,25.20834972,15.69573749,-34.37172704,4.932363969
+770,-96.40444755,43.84058194,-155.3710194,11.48732767
+772,-73.15560515,-61.94144092,-261.6003068,21.57854728
+773,-107.9307848,46.0643806,-143.1468417,21.87973183
+774,127.2929105,-151.0329229,-245.1816979,7.925895827
+775,-82.14636636,96.90948919,-189.7448571,4.825085741
+776,-112.7948634,-227.3130252,-199.2932673,6.21739005
+777,-96.28090411,53.44917319,-196.1767001,17.72422138
+778,-45.91015481,-9.409611049,-306.9524878,20.11629595
+780,-69.16078576,78.75756088,-37.14577011,6.265624249
+780,-79.87794958,57.02653734,-26.88889866,5.754504541
+781,-42.44484442,113.5055583,-553.6117319,4.213062603
+784,-23.13885344,22.15688589,-179.83942,21.15058188
+786,-27.135051,88.96329931,-193.5501301,6.967714598
+788,109.1751121,26.59850287,-76.18,3.831113189
+788,78.89203459,-34.2208228,-87.03257748,4.703046282
+789,-105.5241217,-220.7395969,-229.5932189,4.877679583
+789,105.9839995,-105.1853375,-207.0617303,21.34312682
+791,73.04326903,8.218822771,-54.18659009,15.12543067
+792,-34.8396787,6.548600341,-86.6156801,5.839687338
+792,119.7638134,-20.00968507,-256.6079327,8.101613434
+793,-84.23627067,112.2743681,-617.8992396,5.489049464
+793,-55.76149868,176.2757884,-658.7383274,5.738087494
+797,-93.45976658,60.14386675,1523.530064,7.674509542
+798,-67.81761952,-108.8073081,-97.20666958,8.091312581
+799,93.95958277,182.8100616,-519.1660606,5.525559329
+799,-60.53831978,148.0546371,-648.3714527,7.244054524
+800,-5.325107574,-33.87651995,-217.3421317,9.233993542
+801,-65.27894703,214.8259826,-493.7114427,17.30912384
+802,-115.7646823,41.54110075,-44.56573092,7.57464859
+803,-88.68591428,19.40153987,-150.6757957,5.82215948
+804,-88.09531256,31.8410226,-130.6412308,5.313909599
+804,114.0392079,-22.69021912,-161.1714553,20.91111634
+807,59.49693039,-6.696593702,-135.9209832,14.16781391
+809,-65.36501369,197.6526469,-672.09834,12.449031
+809,35.41588895,217.9560696,-761.0518948,4.928294708
+810,56.39315434,67.68008675,-64.67445255,19.65387738
+811,-100.1410226,-136.6641691,-233.6640856,3.986088287
+812,71.95630178,105.2183743,-534.7339804,7.47852111
+812,35.81885532,171.3443017,-470.1967334,8.727947616
+813,-68.68536654,206.1975285,-685.8740029,17.15613456
+813,59.76390847,195.5534644,-540.4216151,4.25605482
+815,67.69849596,-135.4208561,-167.4867196,6.672413036
+816,97.23149359,-114.9186955,-134.8731105,4.997750194
+817,37.94622827,32.75575024,-37.16949699,17.141662
+818,-103.7436828,26.44662563,-169.0049337,5.687246746
+818,88.80269516,10.87542039,-124.7758984,5.834016122
+820,-84.41936241,5.401025417,-181.75,3.530973761
+821,-71.66642065,-60.40890108,-135.7326014,13.05097889
+821,92.05387089,-11.90929477,-96.7985152,12.97315475
+822,-107.3201535,-96.36995616,-211.97124,15.353919
+823,98.70247953,160.5531927,-418.7378112,13.34340431
+823,110.0184007,156.6589351,-443.8877143,7.199653232
+824,140.9426504,-36.00432282,-249.8855528,4.990997154
+825,-128.3638897,53.10545586,-142.1335065,5.663498473
+826,-75.74263828,37.46097648,-158.6875366,17.2320792
+829,43.1450278,-98.0728056,-137.9507708,5.049919663
+829,-64.18284219,-241.4469848,-232.7504669,4.255683674
+830,-66.69313488,97.04521987,-267.3090047,17.3362496
+833,-28.61357126,84.44425907,-186.5613999,6.545987665
+834,-41.56714983,-53.18554491,-128.3744895,7.98502287
+834,-53.61916799,-51.11956108,-138.5867834,5.313818163
+835,-48.61355881,-4.912857615,-81.28505781,8.349646372
+835,45.60556588,-33.2289356,-141.7458304,12.03275908
+835,56.74074349,-38.92320764,-214.436647,17.60397571
+835,42.18883719,76.001323,-230.0913994,9.883424209
+835,23.6228609,78.54201315,-240.7741212,11.88422357
+835,17.20501649,8.938617838,-256.5635574,8.118983019
+836,-127.5045329,80.97395179,-221.2936606,6.13100107
+836,22.42724374,36.28895442,-86.83608126,6.246461343
+837,-82.8192572,-11.50483317,-154.0991378,9.930839143
+838,-99.09320346,-86.55207171,-212.4084134,4.114597416
+840,-47.53726329,-35.79681529,-137.3325467,13.64151987
+842,49.35261574,119.8406053,-209.6983844,6.943515582
+843,-85.60344693,29.06733423,-107.8464475,7.296371673
+844,-79.93305233,81.93715229,-169.4337204,8.368487089
+844,-7.731399539,58.53652256,-110.5452567,5.127950372
+844,-22.95182604,78.57115637,-136.9010248,6.430802339
+845,-56.87789388,169.460217,960.3534978,9.496379061
+846,-98.7927099,25.94084427,-170.220324,5.414311238
+846,132.7190437,16.66471751,-130.3087179,10.43827943
+846,92.92005202,-18.99832369,-120.0190349,6.500934975
+846,83.22331812,36.04473009,-47.98024541,16.9453939
+851,59.08821583,14.43406702,-83.77592126,17.41146394
+854,-106.7733135,143.1341348,-711.1116663,15.13080337
+854,-98.29382039,97.91485939,-707.3089425,10.15782823
+854,47.75090035,187.9528525,-731.3591439,18.15623418
+854,-88.67952396,200.9356022,-729.0906071,5.963289468
+854,-102.6914791,107.6412561,-705.1730059,9.74508123
+855,-42.20067378,92.20715648,-566.5895507,4.678130013
+855,74.39962496,112.6510258,-534.7158811,4.581766613
+856,-91.94884498,18.62246749,-201.7325834,4.349739416
+856,78.101266,27.79925115,-92.87617133,4.790997214
+857,109.1166375,48.58951079,-120.8920582,21.58311204
+858,-59.56249977,-21.60758611,-184.8701107,6.09648564
+858,117.7817616,40.54149725,-69.84620605,8.605650458
+858,-62.21867479,92.28860997,-213.1976422,4.670798042
+859,68.24385029,83.94075118,-296.8924584,7.068564225
+859,53.46933113,86.9585636,-244.2232438,8.70493777
+859,-91.36992413,-6.167829911,-218.8338691,6.162972621
+859,-113.6850973,61.06780576,-204.5110935,6.67785376
+859,30.71558185,-22.25726581,-151.398632,14.22065706
+859,-64.08663525,83.53715541,-148.0483813,7.901903032
+859,16.20270684,-28.68871508,-142.8056088,8.846172298
+860,54.60755313,121.4927286,-272.9701791,4.866308788
+862,-115.2749392,49.69837489,-162.6187699,11.8061039
+862,-52.79779369,-31.54579675,-131.8715489,9.616085612
+864,22.51629581,85.5374487,-195.8574424,6.135102887
+864,-87.92037654,44.6792921,-151.461638,6.380071404
+865,64.13393756,71.91638535,-126.1763207,8.501262355
+865,-74.89196487,64.17743419,-112.3986425,6.267512807
+866,107.4054265,-98.91303831,-221.6180235,5.850666721
+868,-46.94966448,72.63645381,-95.64452131,27.44242293
+869,40.31479504,-80.72430976,-149.9947759,8.687060064
+870,121.9087601,-67.41580071,-158.8001927,9.061649841
+871,-84.15184617,21.81634424,-184.7857155,18.98004463
+871,-42.46522232,-36.85450686,-123.8759754,19.92726356
+872,-48.06213019,-65.09681526,222.2909831,6.529558333
+873,-112.745883,161.7423069,-498.9031461,5.052577951
+873,-40.21106759,238.0640154,-516.3798885,5.221271945
+873,87.07665986,222.2505983,-465.3562053,12.11647614
+873,55.97275588,250.603657,-517.7658827,6.319450365
+873,109.2006745,197.3028445,-595.8870474,4.519029411
+875,-72.86080331,0.731478362,-100.394452,4.521001895
+876,35.1062029,-25.06165086,-90.50125946,8.620604671
+876,56.35066709,52.95163062,-83.7822307,14.91474445
+876,-70.91353508,46.00620624,-78.16403224,5.973405668
+876,-75.55888225,15.94288167,-80.50207913,4.723904059
+879,-109.4285094,59.59670322,-162.9329603,3.841244999
+880,-114.2130699,67.58978532,-136.7936142,18.67552564
+880,-116.037038,-8.478867028,-126.2935495,11.53208237
+882,52.99602068,85.06797975,-105.4608119,8.117918353
+883,-104.4419748,57.83942814,-124.3083633,7.310399552
+886,-160.8562978,-28.56034944,-269.1687276,5.053693982
+886,-102.1895703,-73.86576556,-220.5362409,4.55610095
+886,-37.53540905,64.04194931,-127.6871014,4.3573681
+887,43.19611173,74.4384859,-200.5233136,4.277202539
+887,-21.95847826,33.48609566,-155.2920257,23.80291305
diff --git a/training/detector/labels/label_job0.csv b/training/detector/labels/label_job0.csv
new file mode 100644
index 0000000..47bdc19
--- /dev/null
+++ b/training/detector/labels/label_job0.csv
@@ -0,0 +1,108 @@
+id,coordx1,coordx1,coordx1,diameter
+cf83e9933c484dd9073ed8314794b9f7,0,0,0,-1
+e67bc6cd24a71a486b626592d591a2da,0,0,0,-1
+21c94e2776145f74697adf8810b05305,0,0,0,-1
+e7adb2e4409683b9490e34b6b3604d9e,367.4375,366.775,157,14.273
+e7adb2e4409683b9490e34b6b3604d9e,65.4399,287.6028,50,63.4256
+a15d4fd19fb32f4858f472962c4bb230,0,0,0,-1
+197e035d3aed52b5a2a0de3ee4d5fcea,0,0,0,-1
+44012bec8f33a785f7844cea8910487d,0,0,0,-1
+8987df2216ae2ab1a907d52bc9dc540d,0,0,0,-1
+f37d1d5c299d4838b294cf82902675b0,460.8231,303.2308,29,12.8655
+f447ac9884a349a4ae56326cf680ae18,0,0,0,-1
+2895ce2fe73dd62554326c3ab1c3b686,183.6989,334.4279,41,31.7992
+f55b8ee990408001671d76c3595afacf,124.2276,176.1796,72,17.7335
+f228862e9f9c6ad7993ded4e088c5050,396.3784,202.7027,106,6.8637
+f228862e9f9c6ad7993ded4e088c5050,164.9059,135.5765,99,10.4031
+f228862e9f9c6ad7993ded4e088c5050,146.8125,370.125,89,6.3831
+f228862e9f9c6ad7993ded4e088c5050,135.1407,229.5333,45,13.1106
+76fff2029e577190ce0bf070192b889e,0,0,0,-1
+c928b4fee44ea322ac65348ae2ff20b8,140.0536,320.3571,75,8.444
+252b5fd5c4a5eb77be4fbe41df49bd07,0,0,0,-1
+673ee14e01a0628b45c78500d402056e,0,0,0,0
+c65d665029c9561bc408f3651c3e2db2,128.9259,232.8426,156,11.7265
+f029c73f6f8753e7447c4e9f22e917ad,197.0287,319.3892,81,10.3444
+a53a4a019a24541c277e0a84301d8ec5,0,0,0,-1
+099cec971282b1531d297e5d0d423598,0,0,0,-2
+d3bc6721c1b0830137515e9c0c31612b,0,0,0,-1
+e858263b89f0bb57597bcff325eaeecf,0,0,0,-1
+a8ff92ed7d8cf90d24f67ba6614c3e4f,76.719,365.8725,38,8.8865
+be4285333fb2d56f78ca867d97eee308,0,0,0,-1
+bb94bc5dd4656a2387bafb6098311175,174.3421,371.3947,134,6.9558
+bb94bc5dd4656a2387bafb6098311175,137.8992,180.9646,86,22.35
+bb94bc5dd4656a2387bafb6098311175,176.5214,399.7096,50,27.2918
+5f19d1c7bd7ceb691639cab9c1c2cb19,334.9423,245.8077,175,8.1369
+a34714908825a61a229bf1457c21ff1f,0,0,0,-2
+2b55d9c3f8e05951c87e90d2361aca6a,0,0,0,-1
+af9a6a57d23dd1889f8d92e5b3a2ddf3,104.7457,308.1101,99,28.6288
+af9a6a57d23dd1889f8d92e5b3a2ddf3,77.0607,178.2303,56,13.1311
+08643d7b9ce18405fb63f63dda258e76,0,0,0,-1
+42e374c728e50cf2aaa78db97f24a82c,0,0,0,-1
+0c9d8314f9c69840e25febabb1229fa4,0,0,0,-1
+191fa0e017185de2c802bbe94edad2ed,0,0,0,-1
+caa6c81b74054858772bda6c2a0e8ee6,0,0,0,-2
+aa594c8968f06fcf374e76bc9a375477,196,395.9867,154,13.8198
+4b6b53281fe1fe797e181a5287df0f9a,63.3892,312.2116,94,14.0259
+e92a2ed80510513497d5252b001cfa3e,0,0,0,-2
+089b8f10743e449a0f64f8f311dd8a46,0,0,0,-1
+68f2b9c1fae9180356cb5c4fa95bd30a,0,0,0,-1
+5a2e359e859d0b0d7c159fff87950852,0,0,0,-1
+bd5bc5a0328033ae48da9e5891704c1b,0,0,0,-1
+c26fbd6a185271f820953be327b5307f,313.5965,286.6842,175,8.5191
+2ea91bfe303ec03f9b0b3603333a3de6,0,0,0,-1
+74dca439eb5b6dfa5e33c6d2119630ff,0,0,0,-1
+6a145c28d3b722643f547dfcbdf379ae,0,0,0,-1
+9d8bdc380b51812ba82a6040ef207c33,0,0,0,-1
+abc526fd74d0fdd73772bc6867bc38a4,0,0,0,-2
+ba8912fd754683662e542f8e737d1230,0,0,0,-2
+415ea74bca59eb0ecd5ebb9c2c545f9d,0,0,0,-1
+a5cac127acd59505d8f1582b95f80983,0,0,0,-1
+9e878fd779fb4d20aaa80db151643442,0,0,0,-1
+28824d52b6425841bb263393c3211693,351.1756,363.1382,88,11.6007
+1c24a09fa32147d9083ff93f171e1102,0,0,0,-1
+75150225ab1f5d910bc64ad68ea4d221,92.4521,335.5479,70,9.6409
+e6f4757b8f315f31559c5c256cb8dead,196.15,406.55,114,8.7404
+4fb3d996e87999e0dfa0009a3e5f0fbc,0,0,0,-1
+8bbad07d91788b97cf894a05a152d291,402.1021,281.4506,133,13.5686
+344ab37041900393b5498bdda6f43cac,0,0,0,-1
+b769e3486463214cf631bf7ab6655801,0,0,0,-1
+3b908e86ea0f7cbd05dd8e0ea6d45d79,0,0,0,-1
+7692b05abf70dbac5292e91918e98913,0,0,0,-1
+a79e929f408cf0fe31f8e3a0904b6d93,0,0,0,-1
+d459ff0332d2b10be26eee73b1f80f7b,0,0,0,-1
+e4ff18b33b7110a64f497e177102f23d,0,0,0,-1
+7f137d30638a87d151ac7e84eeaf48e8,0,0,0,-1
+220223b46a23db0e2b0577170936845d,412.6976,323.8324,183,10.4344
+fb52dd8152e53a4ca7da5403d6d0db13,0,0,0,-1
+eff5b5a7c7245fa8f4661d7e88f8bc7f,154.6842,354.3026,110,9.837
+c7729e1c348f7d54d743388767c69cb4,104,202.5882,98,6.5795
+3b59edf7e74fcff927c912efc0e80f3a,0,0,0,-1
+c1da930ea00f6d11bab7dd34014b7d6c,0,0,0,-1
+37dbe298bb4e0199625689cc35d390bb,0,0,0,-2
+dcb426dd025b609489c8f520d6d644b7,0,0,0,-1
+502e157e6a22166997d054e8920d921c,0,0,0,-1
+2f4645c27f9806daffe7e9d013b4b7eb,0,0,0,-1
+39dc5f09d7b8eeda7f2f02c86f53247d,106.4546,336.1368,119,16.2485
+8fe50e522e082c3752a0814da32f7e4c,0,0,0,-1
+6d60c26d7d35ffd967127b380ff01c12,0,0,0,-1
+ee71210fa398cbb080f6c537a503e806,0,0,0,-1
+c2b4ac9d22e601c5d546318874c76f59,0,0,0,-1
+86b3b918b2ad15df1133b52f418a7386,0,0,0,-1
+7c02c641324c598cd935b588189c87db,0,0,0,-1
+d6fe4bdde1a2cc3dc4efe22becfe22fd,0,0,0,-1
+f395ca14ccb03ad40e98d1473cf686ef,0,0,0,-1
+b229a7697c3efcd6ab82f6f19aff8e8b,0,0,0,-1
+b1091b5af8b47f24c4b94a9d27c813d1,0,0,0,-1
+56d38d6863fd160da38b15bf12f0ed64,162.5375,228.45,139,10.0925
+80a3052f4a1b90fd38fd0def7b79b65c,0,0,0,-1
+122c5c959fd98036c9972eec2062dc59,0,0,0,-1
+0d941a3ad6c889ac451caf89c46cb92a,0,0,0,-1
+78459ff46c9f3b3fa26be2a467515c7e,173.1035,374.4172,50,19.0668
+b79126e0038faca869185cfe49a4e163,0,0,0,-2
+d833b4c1530183c1b3eae02e9a2cd735,0,0,0,-1
+1ec082e8e2fa6eb6366b72a13e47b50f,128.1873,184.9367,62,21.9672
+1ec082e8e2fa6eb6366b72a13e47b50f,98.9352,373.3919,43,21.3557
+7ffe144af38f85d177af286c5d941ef1,0,0,0,-1
+f43843b39a5be8cd30dab59bd11499ed,0,0,0,-1
+0268f3a7a17412178cfb039e71799a80,0,0,0,-1
+4b5970e5edc0d8389cabc6bc5d84265f,0,0,0,-2
diff --git a/training/detector/labels/label_job0_full.csv b/training/detector/labels/label_job0_full.csv
new file mode 100644
index 0000000..b53d85e
--- /dev/null
+++ b/training/detector/labels/label_job0_full.csv
@@ -0,0 +1,1134 @@
+id,coordx1,coordx1,coordx1,diameter
+cf83e9933c484dd9073ed8314794b9f7,0,0,0,-1
+e67bc6cd24a71a486b626592d591a2da,0,0,0,-1
+21c94e2776145f74697adf8810b05305,0,0,0,-1
+e7adb2e4409683b9490e34b6b3604d9e,367.4375,366.775,157,14.273
+e7adb2e4409683b9490e34b6b3604d9e,65.4399,287.6028,50,63.4256
+a15d4fd19fb32f4858f472962c4bb230,0,0,0,-1
+197e035d3aed52b5a2a0de3ee4d5fcea,0,0,0,-1
+44012bec8f33a785f7844cea8910487d,0,0,0,-1
+8987df2216ae2ab1a907d52bc9dc540d,0,0,0,-1
+f37d1d5c299d4838b294cf82902675b0,460.8231,303.2308,29,12.8655
+f447ac9884a349a4ae56326cf680ae18,0,0,0,-1
+2895ce2fe73dd62554326c3ab1c3b686,183.6989,334.4279,41,31.7992
+f55b8ee990408001671d76c3595afacf,124.2276,176.1796,72,17.7335
+f228862e9f9c6ad7993ded4e088c5050,396.3784,202.7027,106,6.8637
+f228862e9f9c6ad7993ded4e088c5050,164.9059,135.5765,99,10.4031
+f228862e9f9c6ad7993ded4e088c5050,146.8125,370.125,89,6.3831
+f228862e9f9c6ad7993ded4e088c5050,135.1407,229.5333,45,13.1106
+76fff2029e577190ce0bf070192b889e,0,0,0,-1
+c928b4fee44ea322ac65348ae2ff20b8,140.0536,320.3571,75,8.444
+252b5fd5c4a5eb77be4fbe41df49bd07,0,0,0,-1
+673ee14e01a0628b45c78500d402056e,172.9333,280.1304,247,20.9587
+c65d665029c9561bc408f3651c3e2db2,128.9259,232.8426,156,11.7265
+f029c73f6f8753e7447c4e9f22e917ad,197.0287,319.3892,81,10.3444
+a53a4a019a24541c277e0a84301d8ec5,0,0,0,-1
+099cec971282b1531d297e5d0d423598,0,0,0,-2
+d3bc6721c1b0830137515e9c0c31612b,0,0,0,-1
+e858263b89f0bb57597bcff325eaeecf,0,0,0,-1
+a8ff92ed7d8cf90d24f67ba6614c3e4f,76.719,365.8725,38,8.8865
+be4285333fb2d56f78ca867d97eee308,0,0,0,-1
+bb94bc5dd4656a2387bafb6098311175,174.3421,371.3947,134,6.9558
+bb94bc5dd4656a2387bafb6098311175,137.8992,180.9646,86,22.35
+bb94bc5dd4656a2387bafb6098311175,176.5214,399.7096,50,27.2918
+5f19d1c7bd7ceb691639cab9c1c2cb19,334.9423,245.8077,175,8.1369
+a34714908825a61a229bf1457c21ff1f,0,0,0,-2
+2b55d9c3f8e05951c87e90d2361aca6a,0,0,0,-1
+af9a6a57d23dd1889f8d92e5b3a2ddf3,104.7457,308.1101,99,28.6288
+af9a6a57d23dd1889f8d92e5b3a2ddf3,77.0607,178.2303,56,13.1311
+08643d7b9ce18405fb63f63dda258e76,0,0,0,-1
+42e374c728e50cf2aaa78db97f24a82c,0,0,0,-1
+0c9d8314f9c69840e25febabb1229fa4,0,0,0,-1
+191fa0e017185de2c802bbe94edad2ed,0,0,0,-1
+caa6c81b74054858772bda6c2a0e8ee6,0,0,0,-2
+aa594c8968f06fcf374e76bc9a375477,196,395.9867,154,13.8198
+4b6b53281fe1fe797e181a5287df0f9a,63.3892,312.2116,94,14.0259
+e92a2ed80510513497d5252b001cfa3e,0,0,0,-2
+089b8f10743e449a0f64f8f311dd8a46,0,0,0,-1
+68f2b9c1fae9180356cb5c4fa95bd30a,0,0,0,-1
+5a2e359e859d0b0d7c159fff87950852,0,0,0,-1
+bd5bc5a0328033ae48da9e5891704c1b,0,0,0,-1
+c26fbd6a185271f820953be327b5307f,313.5965,286.6842,175,8.5191
+2ea91bfe303ec03f9b0b3603333a3de6,0,0,0,-1
+74dca439eb5b6dfa5e33c6d2119630ff,0,0,0,-1
+6a145c28d3b722643f547dfcbdf379ae,0,0,0,-1
+9d8bdc380b51812ba82a6040ef207c33,0,0,0,-1
+abc526fd74d0fdd73772bc6867bc38a4,0,0,0,-2
+ba8912fd754683662e542f8e737d1230,0,0,0,-2
+415ea74bca59eb0ecd5ebb9c2c545f9d,0,0,0,-1
+a5cac127acd59505d8f1582b95f80983,0,0,0,-1
+9e878fd779fb4d20aaa80db151643442,0,0,0,-1
+28824d52b6425841bb263393c3211693,351.1756,363.1382,88,11.6007
+1c24a09fa32147d9083ff93f171e1102,0,0,0,-1
+75150225ab1f5d910bc64ad68ea4d221,92.4521,335.5479,70,9.6409
+e6f4757b8f315f31559c5c256cb8dead,196.15,406.55,114,8.7404
+4fb3d996e87999e0dfa0009a3e5f0fbc,0,0,0,-1
+8bbad07d91788b97cf894a05a152d291,402.1021,281.4506,133,13.5686
+344ab37041900393b5498bdda6f43cac,0,0,0,-1
+b769e3486463214cf631bf7ab6655801,0,0,0,-1
+3b908e86ea0f7cbd05dd8e0ea6d45d79,0,0,0,-1
+7692b05abf70dbac5292e91918e98913,0,0,0,-1
+a79e929f408cf0fe31f8e3a0904b6d93,0,0,0,-1
+d459ff0332d2b10be26eee73b1f80f7b,0,0,0,-1
+e4ff18b33b7110a64f497e177102f23d,0,0,0,-1
+7f137d30638a87d151ac7e84eeaf48e8,0,0,0,-1
+220223b46a23db0e2b0577170936845d,412.6976,323.8324,183,10.4344
+fb52dd8152e53a4ca7da5403d6d0db13,0,0,0,-1
+eff5b5a7c7245fa8f4661d7e88f8bc7f,154.6842,354.3026,110,9.837
+c7729e1c348f7d54d743388767c69cb4,104,202.5882,98,6.5795
+3b59edf7e74fcff927c912efc0e80f3a,0,0,0,-1
+c1da930ea00f6d11bab7dd34014b7d6c,0,0,0,-1
+37dbe298bb4e0199625689cc35d390bb,0,0,0,-2
+dcb426dd025b609489c8f520d6d644b7,0,0,0,-1
+502e157e6a22166997d054e8920d921c,0,0,0,-1
+2f4645c27f9806daffe7e9d013b4b7eb,0,0,0,-1
+39dc5f09d7b8eeda7f2f02c86f53247d,106.4546,336.1368,119,16.2485
+8fe50e522e082c3752a0814da32f7e4c,0,0,0,-1
+6d60c26d7d35ffd967127b380ff01c12,0,0,0,-1
+ee71210fa398cbb080f6c537a503e806,0,0,0,-1
+c2b4ac9d22e601c5d546318874c76f59,0,0,0,-1
+86b3b918b2ad15df1133b52f418a7386,0,0,0,-1
+7c02c641324c598cd935b588189c87db,0,0,0,-1
+d6fe4bdde1a2cc3dc4efe22becfe22fd,0,0,0,-1
+f395ca14ccb03ad40e98d1473cf686ef,0,0,0,-1
+b229a7697c3efcd6ab82f6f19aff8e8b,0,0,0,-1
+b1091b5af8b47f24c4b94a9d27c813d1,0,0,0,-1
+56d38d6863fd160da38b15bf12f0ed64,162.5375,228.45,139,10.0925
+80a3052f4a1b90fd38fd0def7b79b65c,0,0,0,-1
+122c5c959fd98036c9972eec2062dc59,0,0,0,-1
+0d941a3ad6c889ac451caf89c46cb92a,0,0,0,-1
+78459ff46c9f3b3fa26be2a467515c7e,173.1035,374.4172,50,19.0668
+b79126e0038faca869185cfe49a4e163,0,0,0,-2
+d833b4c1530183c1b3eae02e9a2cd735,0,0,0,-1
+1ec082e8e2fa6eb6366b72a13e47b50f,128.1873,184.9367,62,21.9672
+1ec082e8e2fa6eb6366b72a13e47b50f,98.9352,373.3919,43,21.3557
+7ffe144af38f85d177af286c5d941ef1,0,0,0,-1
+f43843b39a5be8cd30dab59bd11499ed,0,0,0,-1
+0268f3a7a17412178cfb039e71799a80,0,0,0,-1
+4b5970e5edc0d8389cabc6bc5d84265f,0,0,0,-2
+0030a160d58723ff36d73f41b170ec21,117.9563,156.4961,126,22.2551
+0030a160d58723ff36d73f41b170ec21,112.0429,116.919,113,10.344
+003f41c78e6acfa92430a057ac0b306e,0,0,0,-1
+0092c13f9e00a3717fdc940641f00015,201.5777,194.2784,96,25.9282
+00986bebc45e12038ef0ce3e9962b51a,0,0,0,-1
+00cba091fa4ad62cc3200a657aeb957e,115.2857,139.5495,70,10.7641
+00cba091fa4ad62cc3200a657aeb957e,111.1147,187.7248,68,16.6603
+00cba091fa4ad62cc3200a657aeb957e,68.1571,314.4048,31,14.8304
+0121c2845f2b7df060945b072b2515d7,0,0,0,-1
+013395589c01aa01f8df81d80fb0e2b8,0,0,0,-2
+01de8323fa065a8963533c4a86f2f6c1,0,0,0,-2
+01e349d34c06410e1da273add27be25c,0,0,0,-1
+01f1140c8e951e2a921b61c9a7e782c2,0,0,0,-1
+024efb7a1e67dc820eb61cbdaa090166,177.0556,302.5278,66,6.7703
+026be5d5e652b6a7488669d884ebe297,0,0,0,-1
+0334c8242ce7ee1a6c1263096e4cc535,416.3348,229.6802,65,24.4366
+03fb0d0fdb187ee1160f09386b28c3f2,0,0,0,-1
+03ff23e445787886f8b0cb192b3c154d,137.0333,344.881,91,24.6537
+043ed6cb6054cc13804a3dca342fa4d0,0,0,0,-1
+0482c444ac838adc5aa00d1064c976c1,0,0,0,-1
+04a3187ec2ed4198a25033071897bffc,0,0,0,-1
+04a52f49cdbfb8b99789b9e93f1ad319,184.5762,313.7952,108,15.8944
+04cfc5efa4c8c2a8944c8b9fa6cb04d1,0,0,0,-1
+04e5d435fa01b0958e3274be73312cac,0,0,0,-1
+04fca9fbec0b803326488ade96897f6e,0,0,0,-1
+05a20caf6ab6df4643644c953f06a5eb,129.719,343.6619,170,22.9038
+0679e5fd67b7441b8094494033f3881f,0,0,0,-1
+0700108170c91ea2219006e9484999ef,0,0,0,-1
+07abb7bec548d1c0ccef088ce934e517,124.2333,139.4714,150,9.8283
+07fdb853ff90ce3c6d5c91f619ed714e,0,0,0,-1
+080e6a00e69888fd620894f9fd0714b1,0,0,0,-1
+08528b8817429d12b7ce2bf444d264f9,0,0,0,-1
+0852f5124d69d7f8cd35fa31e1364d29,0,0,0,-1
+086f95a932c83faed289854083f48831,329.0333,322.3286,142,13.6294
+0890a698c0a6ce5db48b1467011bf8d2,0,0,0,-1
+08acb3440eb23385724d006403feb585,0,0,0,-1
+09b1c678fc1009d84a038cd879be4198,0,0,0,-1
+09ee522a3b7dbea48aa6d39afe240129,0,0,0,-1
+09fdf599084b816247ba38d95b3c9d80,0,0,0,-1
+0a099f2549429d29b32f349e95fb2244,0,0,0,-1
+0a0c32c9e08cc2ea76a71649de56be6d,0,0,0,-1
+0a38e7597ca26f9374f8ea2770ba870d,101.681,357.681,59,16.9794
+0bd0e3056cbf23a1cb7f0f0b18446068,0,0,0,-1
+0c59313f52304e25d5a7dcf9877633b1,0,0,0,-1
+0c98fcb55e3f36d0c2b6507f62f4c5f1,0,0,0,-1
+0ca943d821204ceb089510f836a367fd,85.8333,334.519,38,42.2642
+0d19f1c627df49eb223771c28548350e,0,0,0,-1
+0d2fcf787026fece4e57be167d079383,0,0,0,-1
+0ddeb08e9c97227853422bd71a2a695e,0,0,0,-1
+0de72529c30fe642bc60dcb75c87f6bd,0,0,0,-1
+0e7ffa620c6db473b70c8454f215306b,0,0,0,-1
+0eafe9b9182b80c6d67015a2062f5143,0,0,0,-1
+0eb39d23d0f68ade9b5d8e6b3aee04d2,0,0,0,-1
+0ee336c585bf7eb1011df476891c5102,0,0,0,-1
+0fb1b54da1e66c60a57db9c52f945e25,0,0,0,-2
+0fe244f21893c45fbb877f54d008518b,0,0,0,-1
+0fe9dd36f4dece7f4ec017433c4d4a50,0,0,0,-1
+101a2999d28ce05788e6add3a28d4726,0,0,0,-1
+1030bb45e9f660c3466f013dcb270520,0,0,0,-1
+1098cb63ea33f752a850929234576bcb,0,0,0,-1
+10a9c32039971eb12f3aecf76ac20f8c,0,0,0,-1
+10aa518193fa5b89b305a806d1dfb150,0,0,0,-1
+10f03fe0b77d39c758d6fb12304edfdb,375.9667,379.6238,55,12.068
+10ff16e329c64a6a290a7a4139a5f4ae,0,0,0,-1
+11616de262f844e6542d3c65d9238b6e,0,0,0,-1
+1183f213c1c821df18aad63890920403,0,0,0,-1
+11b09ff9de7382d83f79cc81f89f5894,0,0,0,-1
+11f10c2a0bfd231deeec98d69e4d0767,157.7571,221.7571,89,18.9247
+124c4188604434bcdec8358c8ddf9a8b,0,0,0,-1
+124e68a78f9c092a2f16f9214e91268f,107.0909,404.2424,83,9.167
+1278988821a696e534c6c93ecdd4ff0c,0,0,0,-1
+1344e604281e68ac71f25c02e7637992,322.9381,300.9952,220,15.6114
+135f21a84ac903a1d8dfbb0dfe46d792,0,0,0,-1
+14248ec22193bed1e087755df5a28509,0,0,0,-1
+149ff4b37a684a73869d2d88e3fd4d0e,0,0,0,-1
+14afefc82d992018c485949285d20c03,0,0,0,-1
+14c534e0b7c3176d9106c6215d0aa8c6,0,0,0,-1
+154a79706bcecd0402b913d4bee9eed7,0,0,0,-1
+155893351afed6c68893397d19555fd8,0,0,0,-1
+1615ace332b9d79be4e0e9fa32c71e9e,0,0,0,-1
+1631637f08f27347e8f23d7a0e18c100,0,0,0,-1
+16377fe7caf072d882f234dbbff9ef6c,0,0,0,-1
+166a2a476b7b84c975fb65162acc0798,0,0,0,-1
+16a4184e565f589622a70e82957ab54e,421.8281,262.9063,89,9.027
+16a4184e565f589622a70e82957ab54e,186.1667,356.4231,119,9.9656
+1748ad43b222be66f3e5ae4bd70c02ac,111.4333,335.1286,91,24.2894
+174a9fc87f54d6def3730954fbafc99d,0,0,0,-1
+178663e1e238cdfa4d4eb9679e5d0aa4,0,0,0,-1
+17f5ae9fa49c4e47624f344d29bd03eb,0,0,0,-1
+17ffaa3e8b53cc48e97fc6b87114e6dd,446.6,269.89,83,15.9577
+180737a8b34cf2c88b00dfad3e7556ae,0,0,0,-2
+186a0877503b047a77eb9b38083be9c1,0,0,0,-1
+186d95f7c17fd666726c10251072d44b,391.8143,355.2429,135,18.9639
+18f49fee33af677f0ce2ba655c5ec835,0,0,0,-1
+19409b302d6c143d4f754146e91d4cfe,0,0,0,-1
+195842462645f0f331147a4c6b129a37,0,0,0,-2
+199ff05d08ade6e298d37cc542bc3565,0,0,0,-1
+19bb6a9bc007ad75a4777e5298354cb4,0,0,0,-1
+19ca60da880961c50f1b99b66f252e8f,0,0,0,-1
+19d95b5828aeba8073fcbb12979f312b,0,0,0,-1
+19f3b4dea7af5d6e13acb472d6af23d8,0,0,0,-1
+1a41350d4bbd74b7e0e28239cefa84c2,0,0,0,-1
+1a91ca95390756518700877893ac195b,0,0,0,-1
+1a9e2aad4b87512636f4f9d82c36a3ef,0,0,0,-1
+1acbe17dc8f9f59d2fd167b2aa6c650f,0,0,0,-1
+1b17c83c3b0cb973e41f9121e562d030,0,0,0,-1
+1b2355e6054759f2f0eb2542ed382b78,0,0,0,-1
+1b7ca8dad5c36feb0a6abf8079173e22,106.0677,199.4135,175,13.0131
+1bb17a55702a78142cd05cd1063c82c8,0,0,0,-1
+1be4cf2de84adac4de0e090c9a15461c,171.7762,385.1095,42,17.7496
+1c05dea5723caf192af34ceb5804468f,0,0,0,-1
+1c42a5da837f4122d2c3b59ca9b5f0fb,0,0,0,-1
+1c498f306808952739e7a3a3a2439d1e,0,0,0,-1
+1c81d86923dad37b411f3a5936eb622d,0,0,0,-1
+1ddb5d17d9db61c8ea0fd58d00df05ef,0,0,0,-1
+1e33cb12436a64853c1ae9e918633e05,0,0,0,-1
+1edf5480bf676f8342a7d516bab58fa0,0,0,0,-2
+1ff6e2a80eb74396e09460c61ae69fb0,0,0,0,-1
+204bdd4a15f023eea66190972b66fd0f,0,0,0,-1
+20809d879e5a966cc537beb42735a67f,0,0,0,-1
+20c73e37fc89e007ae5b242480830860,0,0,0,-1
+2117642550461db380a019bbd10a95e5,0,0,0,-1
+2143d78ca33eb69f667edd80ddbff6de,0,0,0,-1
+21bdacdcdb87bf401f34d5d582247c77,0,0,0,-1
+21cfe28c4a891795399bb77d63e939d7,0,0,0,-1
+21d449f3ae00ea302e5aa15d7df65465,0,0,0,-1
+2276fd918ac100cec3ed8036f6ad401c,132.0354,167.2035,57,11.9948
+2346e52f9370d9dd58172eb44b2b5d87,383.2357,206.5892,65,19.4461
+234ac5dd589d09a4b2a753ff206d5588,0,0,0,-1
+23e309ef3a674bcd9c8df40614b93a8e,0,0,0,-1
+24031ba88c58797148475f6d4d5a085b,52.7538,299.1692,53,9.0973
+24626abe1c4544fb39d4e96e33275789,0,0,0,-1
+24deb9f7adc838e4a4aaa2c905c548e6,303.4333,327.2048,215,7.4152
+2505ca2e3cd132f69fde96ba4bb50f7b,0,0,0,-1
+25196c504274d166e81c745d32f30c72,0,0,0,-1
+25782c40c29f7d774f8b644f3e68b590,0,0,0,-1
+25a3b616f6cc89e74f6502d65b687972,363.0484,289.4032,59,8.8849
+25a3b616f6cc89e74f6502d65b687972,340.9344,306.6393,58,8.8129
+25c1c4f008e8addc4d386cab58815052,0,0,0,-1
+25c369973827571098bdebf2a15c6ef2,0,0,0,-1
+2615d445b6d3865407d1a4422d25058e,0,0,0,-1
+263fa87394ee296e31234364e75d05e2,0,0,0,-1
+264e5829ef58570c243bfd961098343f,0,0,0,-1
+26a2b8d6b94ee16ecf88fb28c57f377e,0,0,0,-1
+274297dd9a4f66148754944ae2b6731c,0,0,0,-1
+27e9f8b51aeee67918221f2df98e9cbc,0,0,0,-1
+28054f63c5a6ef24e06d8c34258babd6,360.2958,201.5493,119,13.4462
+28352e12fe29361dfd9613ed2e729192,0,0,0,-1
+28621a6988deb389673605447f46d3bb,0,0,0,-1
+28649e08938386e3b8eaa4a84baf5982,0,0,0,-1
+2885e3af725bc58dc1522d4bfb24bb2b,228.8,332,77,14.4943
+2922aac33a190fd3939de337fe3f0a34,0,0,0,-1
+2950df9632577cb4b3af2dbfe2086b11,365.8047,332.5742,48,18.0541
+29883252ce0ce3e052ce8cf4932623af,0,0,0,-1
+29a2105c99e7677c30c7fd0b2edb9fcd,0,0,0,-1
+2a48f50391e22040f28e258a74dcaf95,0,0,0,-1
+2a549c66f24af964de6f25165c55e331,0,0,0,-1
+2a6433cf347f7bd52ab796f083003832,0,0,0,-1
+2a65c8b6d5cc50866de8caa4caabbb6d,102.0556,273.3056,86,6.7703
+2b0ea2696c8a02af5ac22f142be28e17,0,0,0,-1
+2b2a95f76d7b6712690ee7be6838f868,0,0,0,-1
+2b89691a0744504491ef91d711d94918,0,0,0,-1
+2bb5f7e8f10e1e39b7f81b5aa98676ea,0,0,0,-1
+2bf773632e786951d6d594939e6f4713,0,0,0,-1
+2c51b9e7af4850d817f4aa0ddf90b852,0,0,0,-1
+2c8e0b1e8a3f10b1d59e4aa8fe68a32e,0,0,0,-1
+2ce2565b9839d8812cf0f9ad80371d3f,178.3547,178.5867,65,21.851
+2d8152c603e6c49593578bde8e388860,0,0,0,-1
+2d81a9e760a07b25903a8c4aeb444eca,150.8872,386.7216,38,16.5335
+2dabff545dbfcb9e0efd92220c6aebcc,0,0,0,-1
+2dbb8c6c6ea4ff5c62b34bdf9ea03158,437.3064,343.3144,30,11.7607
+2e26f46f1edc232be164c1fe2712e96a,0,0,0,-1
+2e59e2064d391f4b2587a08aff671399,0,0,0,-1
+2eb8aedb5274414e05041b7be65db3e3,0,0,0,-1
+2ed2ec628e6ad9d0aa8c2a9b7bf4c4ce,0,0,0,-1
+2f4e4a808cfb348d6ddc81de96f72077,0,0,0,-1
+2f7088e4008c0ef2c88b6764af8c8815,0,0,0,-1
+2fa939efbc3e1c2bc57ba5a98922ff3b,0,0,0,-1
+2fced53a125854edb9284ff12795caf8,0,0,0,-1
+2fd66be0a5e07b8bd4be1d8169cd846f,0,0,0,-1
+302336ac736ed66077456775a0a99adc,0,0,0,-1
+3043b5cc9733054f3ab5399c3c810406,0,0,0,-1
+310b403db75226a9a44d9a29c18917b7,55.1862,268.4626,77,15.7816
+313efe2e7ecf18a8d484f8b42f30da3e,151.5708,178.5721,62,30.9956
+3170d41d2bc132db30399fca6bc6f376,0,0,0,-1
+3187b6cf14ed2cbe611b01da5e161f21,0,0,0,-1
+31c090cf66ec7bf090801d14d63199b5,0,0,0,-1
+31d037f6e359b56aec064fd3e348adb5,0,0,0,-1
+31e82ed2c875eae8dfbfd70ac440458a,0,0,0,-1
+321364cc2393dccb7ba8894ee9d2b269,0,0,0,-1
+322d09835e9c6f621262ee68fd3ed596,0,0,0,-1
+323792e42c4f43448b2b1a9651ecb779,0,0,0,-2
+3244f802b7bd7c02ba7a8473802e947d,153,157,71,5.1709
+327c4e9f365aec05222e253d1a80a1d4,154.9887,219.245,65,28.7184
+328138837e6db638913332acb79c703e,0,0,0,-1
+3295f3f392d8e130155c8912b60161b5,0,0,0,-1
+331b14e413e88542855664c845c08c63,0,0,0,-1
+33293edbc834da033aa061f7d6a45fa1,0,0,0,-1
+335b129aacabdf9269b0bb12f148d15c,0,0,0,-1
+337e7a428e7342d1e7f53a04247f7ad8,0,0,0,-1
+338f9c6da34f61091a4c44b074b2f9e3,0,0,0,-1
+33da5fb759223c316e8cec9d884d1584,0,0,0,-1
+33e0e8629a377e4554b26e60a1007788,0,0,0,-1
+34007dd2549af2b82cc1206e550b5100,167.8333,206,109,10.7047
+3464083b3e6e7c11d1fba925f0b914cd,0,0,0,-1
+34b00e3b98072207edd20732558f7ab5,0,0,0,-1
+34cb3ac3d04e0d961e7578713bee6bb2,140.6335,356.3024,98,12.3044
+35105d801880bd889bac5ee3771ed38b,0,0,0,-1
+3557455d81f42ee54ad0544f36933e9a,0,0,0,-1
+356bc45910503ffde017a066581a3798,0,0,0,-1
+359951e3d2768249211361665b99b735,0,0,0,-1
+35ab1899e939be4e67923a1624c91365,57.9206,275.982,64,11.701
+366cfab448dbe55fd63b01adac0b1c56,0,0,0,-1
+36d0dff4c9eb340475888c2f93359e43,0,0,0,-1
+36dcb6b7463ada9ed78ce902d6f8ddc2,0,0,0,-1
+36f4fca6bbd993088ee024f93a61b722,0,0,0,-1
+37006435aca7184571bba3c907141e82,0,0,0,-1
+37030ab5889febdae6725740aa627f95,0,0,0,-1
+379d84cd171e6c0e58455c2fd0cf57ef,0,0,0,-1
+38d89e67d2ea7e2ab023c10f5f19f716,0,0,0,-1
+3938d2274f0576b70fffa9aa68af8874,138.241,163.5334,85,11.1278
+399a263bdfbf26c6969d8af98774be8c,423.6348,334.4279,65,19.4309
+39c3a2d2ca67bc7a1a22240ea571d50c,0,0,0,-1
+39c404ac6b5852fc8ff00d34bd35294f,235.9927,176.8632,83,18.3678
+39c404ac6b5852fc8ff00d34bd35294f,115.6829,375.4426,60,10.4344
+3a1a293ecad44010da9907bfc91d94cd,0,0,0,-1
+3a3a7a6b3d2a4ea6b1f5bc6ea715eab8,406.8872,337.8458,67,13.2727
+3a78dcf53effd732bc3880c029154272,0,0,0,-1
+3aedb9550977ed35e7d44555207ef739,109.5307,394.241,43,11.6409
+3b7384f374b73d2bd589ccbf1b651820,0,0,0,-1
+3b78adbbe463aba48bf29613ca37b2ea,0,0,0,-1
+3bbab45d770ecd681be143f67cb4e5f3,0,0,0,-1
+3bd4f83c5930e8c1e193ccc463543745,0,0,0,-1
+3c2dbbdeb857504a8b501fc013b99c90,0,0,0,-1
+3c5a0fc6890a1f84211cf8a75c1b83c4,359.7203,154.9887,78,10.2764
+3c73f5597780b7312b380373fb897f40,438.6736,164.9005,42,28.1515
+3c86ed658e82e542bc542886a59ea4f1,0,0,0,-1
+3cdd66bf14f0cff5cb46e95d5867de0d,166.5441,380.3824,64,9.3049
+3d2b2b0fa9697b298fbbc033481cdcc4,0,0,0,-1
+3d4e602819dca0f5eb48953841ff11d6,0,0,0,-1
+3d521ee3776eefb65953f89c0e1a4f96,319.0474,386.0381,81,11.2115
+3d5351d09a432a8de88e5b270d419ebf,0,0,0,-1
+3dfe8e80106f4136d2933ff72a16035c,0,0,0,-2
+3f057e68a02e9951b268227649f4a7d6,67.5217,313.9565,45,7.653
+3f28787cc3343445a8c5ecc4dae27a25,0,0,0,-1
+3f37745d6516c29c597b797c50fe7839,0,0,0,-1
+3fcfd27d83883f454ba2fe58dee4abea,57.5788,334.0861,33,18.6706
+402a18fa05523f80abb1e6d97793cc19,0,0,0,-1
+404e5dd2b032a223282f5a5e73c05418,0,0,0,-1
+4062f1ad138218af5a3dfa3186d2afe1,0,0,0,-1
+408646e125230c495be91fe171da736e,0,0,0,-1
+40c044145f5c87c12bd8c725924add3c,66.1235,200.1048,87,10.1621
+40c044145f5c87c12bd8c725924add3c,100.3889,382.7037,49,8.2919
+4131820511c86a5e6b1e7721ab687049,0,0,0,-1
+4165b6e956c0e46e94abf7d98f8d8fe2,0,0,0,-1
+4209cb1fbce28cd68da900eb9bef26b3,0,0,0,-1
+428e25dfddfe731fc73f4e1739422181,0,0,0,-1
+42bfcfb0e3965039947bd905b2fc3915,105.7586,329.4655,123,8.5935
+42bfcfb0e3965039947bd905b2fc3915,72.6175,283.1595,81,9.7873
+42bfcfb0e3965039947bd905b2fc3915,325.8832,359.3785,85,7.2665
+42bfcfb0e3965039947bd905b2fc3915,128.3291,76.3772,75,9.2977
+42dbd247a9e5f710926b7c049a00ff48,0,0,0,-1
+430596d1bfa6ec9a7bfa7359194a561c,124.9112,392.1903,104,10.9586
+432f8765e6b590ec00cc34c8d88456da,0,0,0,-1
+4348beb99dacd2cbf14983a2c64a00c6,307.0848,345.3652,60,16.9246
+435cd5883a2014f295a8081ea098674b,0,0,0,-1
+436fd6ccfc92afc44c7d3ccfe26b6129,129.3545,253.7657,63,26.1999
+43933b4021d93dd64854f318656c7d1e,0,0,0,-1
+43fecc8947e4fbb47968dc8ef7d8f4ec,163.1916,215.4853,67,8.7541
+43fefd3f810ef71e0073d2415e7a6713,0,0,0,-1
+440fb90654b1436e7c3bbdac991b8c1d,405.1782,200.4466,50,20.8687
+4419818b57ef8b0f8d6d95594adab922,63.9808,314.7404,40,11.5073
+448ce51772879fcd88f61c07b06347b2,0,0,0,-1
+44cd94d1228f4a70753b5dfc12703414,312.8952,358.0113,39,14.992
+456a7dd28233b398ac83f03c80447b5a,110.8979,348.0995,121,15.9583
+456a7dd28233b398ac83f03c80447b5a,122.1769,353.5681,114,25.2091
+45a8417be8f56b401bd7b5d106f5acdd,0,0,0,-1
+45efbc7cc2657278f878bc973cecc141,88.6816,313.237,68,15.2853
+45f4141cfe3f110f9db4e1e113d15684,0,0,0,-1
+46199ffd681fd429aca3823c76f1034d,0,0,0,-1
+463b67fefdde16ba3c4a4258de1f38e3,0,0,0,-1
+479078cdf18cd6b677b79d2d9b075d81,0,0,0,-1
+483b89a4ffbbd85acc8b9af5a541dd4d,406.2036,175.1542,84,10.3444
+4842c8c0a3f387effde44cb9b3d3fd2e,0,0,0,-1
+48713d11ced3c60a531e6e80258d6425,0,0,0,-1
+487cc9003c99fa95e9a9e201d396992c,0,0,0,-1
+48fac79fead32f2b10e37752cb077af6,0,0,0,-1
+493641ef65ee95fe994d4789aec1db3b,0,0,0,-1
+494b9a6714921a446b32959ca291b050,0,0,0,-1
+494c42cb61c1e4a02504c16fe09a8129,145.4186,274.273,182,10.9372
+494c42cb61c1e4a02504c16fe09a8129,135.3205,342.8333,186,9.9656
+49a29b3f5bee32b350bedc4cfbad8e9c,0,0,0,-1
+49b5b3444cf977439600dd06e8dd84ad,0,0,0,-1
+49ee28b71e02be4689e3fb0ba2a32c2b,0,0,0,-1
+4a1391269629d20359325873d11413c9,0,0,0,-1
+4aa3131e76b28e30235664087407edc3,0,0,0,-1
+4aea6c3360cd923d25f33ec5b5e643bc,0,0,0,-1
+4b19444c570185fc4606e4e29fd1ce1c,383.6455,151.229,116,16.4201
+4b2f615f5498ee9d935b0229a2e6bb19,0,0,0,-1
+4b351d0c19be183cc880f5af3fe5abee,365.48,290.5467,165,9.7721
+4b7f72b889e85b479305f8fbc8cc4f48,88.6816,214.4599,81,15.603
+4b7f72b889e85b479305f8fbc8cc4f48,82.5663,291.6627,95,10.28
+4b8e47f2a5edda13b971da27317bfc6f,168.3184,312.2116,134,39.9645
+4b96e8e085d7ab16c8054654fe586553,0,0,0,-1
+4bf6fb574a2ca2da551609e98a573e54,0,0,0,-1
+4cc309d81bf3685d7def772862375a2a,0,0,0,-1
+4d207541fac845d1a369a160f15d55e6,0,0,0,-1
+4d621b0adb6b46b353056e1843621c5f,345.7671,228.3562,110,9.6409
+4d86e1657d46b9ee44c2c434fad231ce,325.1962,313.4491,45,18.3687
+4d8f4de444a1f453e7ad32d067b0f630,388.0888,236.6762,120,19.3345
+4dade0813da186d968b4b8c4952cbb0c,0,0,0,-1
+4e9c2cbf385db44b6f5e6618f47318d9,0,0,0,-1
+4ecf053654c565e4a5d0f37811eade66,0,0,0,-1
+4efa432089851f50a5f53fc5a12e806a,0,0,0,-1
+4f1573f5cab1aaaebff33287682c5fbd,0,0,0,-1
+4f3039ae82f8cc764d1ec21116f54a07,0,0,0,-1
+4fcf8b00ea7a99162dc70aba253ba669,176.9202,134.4366,110,16.4682
+502d4601458807bf0089e6fd07825357,0,0,0,-1
+506b07466777f6c6f4dd50a42896a2c4,0,0,0,-1
+512397206b42f1f8d009113511ae2937,86.2891,285.2103,118,16.5335
+521924ac2f00a62cc63f679de7e599cd,0,0,0,-1
+5253d873ff82e3fa69e30e542d13a4ce,96.34,364.9,40,7.9788
+5275c7ec0f1d80c829611c378708c05b,58.323,264.7267,103,14.3175
+5278093ed7187e1a8be518d954509da7,0,0,0,-1
+529e4dd38822b413a4a87e6f4faa5f23,458.64,315.6,30,12.6157
+53087ef723e2433ad0b8041e408c6f8c,0,0,0,-1
+5368521797323c89292781b8780e45b5,0,0,0,-1
+538600927ec2970552917a29b490b5fd,0,0,0,-1
+53ddfb7769619035ad7f8f58c72f697c,0,0,0,-1
+540dbb66efa0f76499464689756e69f4,120.5208,371.2013,81,13.2987
+54162a514a5e2beb54e4b7aff41f5dfe,0,0,0,-1
+54d421d543e9e6dc8db10066a5867081,0,0,0,-1
+54df448f6c74df6bfa6b75c05393ace1,165.7025,340.9256,149,12.4122
+5518b27f000e34cf2db5a362f4fac613,88.1,195.6818,69,11.8345
+5518b27f000e34cf2db5a362f4fac613,62.7068,216.6316,69,13.0131
+5518b27f000e34cf2db5a362f4fac613,76.9675,192.3338,65,16.3552
+5518b27f000e34cf2db5a362f4fac613,68.7048,216.8857,65,11.5624
+5518b27f000e34cf2db5a362f4fac613,118.9502,248.403,64,15.9975
+552ef3f04be2073d2cf8a52431576c24,0,0,0,-1
+55baceb599dc8aefe4b13c131d0531df,0,0,0,-1
+55d88980822c2e5d39b3d0ec172fa101,0,0,0,-1
+55e476ee19742fc09c4ce5e6ebdc13d1,0,0,0,-1
+55eace190c5917cdfb390ca652149fbc,0,0,0,-1
+565cdee745ea4e6afc0f7daae81a7963,440.687,331.3052,58,19.3289
+566a5d958f17d2fc44d4a1ec00401034,0,0,0,-1
+56995718fdd0a0549d0e7f11eb307f34,0,0,0,-1
+56e0f421b7faddcae027d7feb6dae8cd,0,0,0,-1
+573e900142c9e6e7b32ed9e5ffd5584c,0,0,0,-1
+5765dc0dbc8c02a4c862563eac4950ef,0,0,0,-1
+579dfed23d49414a2c080bbf9d7f958f,0,0,0,-1
+57af0020213d64598ede82fe9d6bb8b3,0,0,0,-1
+57f5dc474b6a35d02542299dd09e68d6,0,0,0,-1
+5818c3be99a83ca8c951ff3434750d6a,0,0,0,-1
+5861f8f8e35c0713c61e8ab3bc54c905,0,0,0,-1
+587d6230f2bad2525c47632fd792a895,0,0,0,-1
+58bac12ccb44919bbd64271f38ee0584,0,0,0,-1
+58bf189f6021ecea213c13eed7484d84,0,0,0,-1
+58e4646cbead2fc4a6a1f86bf806e76f,0,0,0,-1
+591f6b47c1362410e7f4c13afbc99d79,0,0,0,-2
+5968ac45330d7f24b041a73925818269,207.9597,313.3519,203,39.7462
+597643aa6bb96b705eac52e03a307d6d,0,0,0,-1
+59e4985cd165f3abbe888475ce564f3a,0,0,0,-1
+59e4e8889ae68a75227b2bd02c1d1b96,0,0,0,-1
+5a06cb92ba004e2265ab087b5b09e33a,106.5571,208.9571,50,9.4036
+5a57009fcdea02d30d31a47d2454dc29,0,0,0,-1
+5ab68460985d9ed8e952475b402ddd62,0,0,0,-1
+5ae03fb6d9959aa93d1177cfd70cf760,0,0,0,-1
+5ae60d42ec7eb7a79ce9a72967cbb6aa,0,0,0,-1
+5b4f56936ab57ee5b30d8752652ee5cb,0,0,0,-1
+5bb9185543527cd034aa48fc0b623874,0,0,0,-1
+5bf71718aa1bdcada76f0683f8d6b41b,0,0,0,-1
+5c0d992d01e6383d5684b8ac5d7143b1,0,0,0,-1
+5c4c25f93529bf21469f81a0acd5d324,369.7963,371.963,12,8.2919
+5c69c62e94dde61c690563eb3553a561,192.9987,361.2273,56,58.7857
+5d240c6a6d3009e61cb09ce49f641b4c,0,0,0,-1
+5d801b07718dc9a1ad2bf701523a0f74,198.9869,318.1307,71,13.9573
+5d801b07718dc9a1ad2bf701523a0f74,470.2766,319.0039,67,14.764
+5da3dd09c0d0d597287a9a1046cced37,406.4429,208.6247,63,14.2147
+5e21909f11ec07f75460fe16b6c0185a,68.0568,218.2955,60,10.5851
+5e371e8fda27df3e5cc2548868229d5b,0,0,0,-1
+5f383eb9c3d8ea72ddec7e2e874d577d,42.0584,218.5987,50,12.1339
+5f383eb9c3d8ea72ddec7e2e874d577d,355.2429,368.5416,51,38.6578
+5f3b9b59f957fea0a5e8cc506e12652e,0,0,0,-1
+5f4e23c0f76cd00aaaa6e03744bbc362,0,0,0,-1
+5faa4b8d9e86c157b7b16e67f22e7210,0,0,0,-1
+5fe048f36bd2da6bdb63d8ff3c4022cd,0,0,0,-1
+60018d051926d01b38dd16e44159610c,430.9,134.95,134,7.1365
+605d3633c1625b4be151d38aad43de94,0,0,0,-1
+60638c0dcee9e5adfcac3b4f57d1366f,0,0,0,-1
+60a4915d8662dff30dc596ebccb83b3c,0,0,0,-1
+60b1526597b82c98ce96fbe5014c0f2b,0,0,0,-1
+61406252b7c29fbe372adfa953d95199,0,0,0,-1
+61917cf6407e793bc0edb60850009e85,395.6271,214.6949,174,8.6672
+61917cf6407e793bc0edb60850009e85,401.1234,149.4455,103,9.5204
+61c0247462b00b95c4df16edd4486a06,0,0,0,-1
+61ce76681b4a68b8d0f3b724c1e844b3,0,0,0,-1
+62099cb774faa70d28d2c5cb1e235270,0,0,0,-1
+63d907adcf3f12349a0c2c8921d38e89,207.9597,266.1416,104,27.4885
+642c43727eee4bda71c0c30bf5cf1a2b,0,0,0,-1
+645e7f46eb9b834153ecf8e2b2921fe5,0,0,0,-1
+6540e089936a6c9d1f11939e96e6ab18,0,0,0,-1
+654f2095bace27af870cdfcc66f9717c,131.4922,189.0091,94,8.6442
+657dc5d2bf8ea210d912dd8320481068,0,0,0,-1
+65dd5d9d5b894e5f0ac3bd6c1384c46a,0,0,0,-2
+65f596f75eebf7935554eaed3c8172ce,399.2267,224.7867,111,9.7721
+661ffa992ed2c23c37f1e7b82dc834d7,0,0,0,-1
+6629e23c3bdc8dc8161b3caa8a6048c1,0,0,0,-2
+665ca5ce18dd06722a4c4436a85246b2,197.6532,409.7675,117,18.901
+665ca5ce18dd06722a4c4436a85246b2,0,0,0,-1
+666fad0dca00694381eeec67adc909ec,0,0,0,-1
+6675d3cc20585f44d4c45746cb1002d4,328.0575,408.799,70,27.7317
+66a94647459dd5a13f4336e1421119c5,336.4761,317.7257,57,14.6214
+66b7666912e1d469cd9817a1cade694c,0,0,0,-1
+66cef72d8428dbba31f2ab01abdaf6ca,0,0,0,-1
+66fb40934f0be4b301fe27db7fb62299,0,0,0,-1
+67ccc2ecd7716e1cab05caaedea99f4b,0,0,0,-1
+67e87fa621f2e3e838b1b17a898d5b41,0,0,0,-1
+67f7f74220c08faa756b34cb81b203a5,0,0,0,-1
+6828335aec9aa0d0053ec0949319aa4b,0,0,0,-1
+68a1f729eb1e2a791fe8170ac6631828,0,0,0,-1
+68e905099a1c18242aba55c9901eaaae,0,0,0,-1
+6997b392b28529c9ab67add45055fcf7,469.2593,287.8782,55,15.0751
+699e4f02a11a33930a14b13071d24eb0,0,0,0,-1
+6a08bc7a3156caf9b07bbb1f9b2861d2,0,0,0,-1
+6a7f1fd0196a97568f2991c885ac1c0b,0,0,0,-1
+6ae190bcd3fd9c581db4120f4465d65a,0,0,0,-1
+6ae1b284936accdc4101c6daaaa2e0d3,161.2175,131.7526,53,10.4095
+6af9fecd6807921fa9fe10f0391aa453,0,0,0,-1
+6b4837a316e688d0ba125cc1e545d383,0,0,0,-1
+6bebfec174e8a6e8d4b1653c13fcdbe5,0,0,0,-1
+6c1136ce7fbc5c7b503aa08da6abedd2,0,0,0,-1
+6c56e9802fb6346db58bd5daf160f9be,111.6667,174.125,93,5.5279
+6c56e9802fb6346db58bd5daf160f9be,333.4148,347.9559,148,17.619
+6cf71f5017945c9dd8bc0f5126eeef5b,0,0,0,-1
+6d01b46b619b9f6d8c78dbd3f6864372,411.0949,243.1069,186,9.5894
+6d01b46b619b9f6d8c78dbd3f6864372,419.7784,290.1364,84,14.9696
+6d38cc9a6de069570a5d2efbb55a7f63,118,209,123,5.1709
+6d75fe2462284150249a04d78781189e,0,0,0,-2
+6ddb331865608b8dfb8cac6d873eaf62,0,0,0,-1
+6e3a7f8ef70e26252d25cc105a945f86,204.8408,355.9918,34,11.3773
+6e5f12931ef179cc21382a59f5acab86,0,0,0,-1
+6e6d5603fb8fcf523f86ac0856e50236,0,0,0,-1
+6f38eb7988753c6a978d0da80dbc014b,0,0,0,-1
+6faabf4152bf0ebfd91f686bc37a1f16,0,0,0,-1
+6fd582d25eeb2250c2b0996c4216deb9,0,0,0,-1
+700bdc2723c2ac75a8a8376d9ca170ad,0,0,0,-1
+70287a7720e0d90249ac7b3978b7ca40,0,0,0,-1
+7050f8141e92fa42fd9c471a8b2f50ce,0,0,0,-1
+7051fc0fcf2344a2967d9a1a5478208e,0,0,0,-1
+7180c83eb184d5c9dfcbda228ab91213,0,0,0,-2
+718f43ecf121c79899caba1e528bd43e,0,0,0,-1
+71e09cd11d743964f1abf442c34f2c9d,0,0,0,-1
+722429bc9cb25d6f4b7a820c14bf2ab1,0,0,0,-1
+7239b3a904f39b25c4e303c10a24621a,0,0,0,-1
+72609c2be68be9d7c9cde3d0127c05ac,0,0,0,-1
+72a1e35c34052e163f61585ba0c9daf4,0,0,0,-1
+72b080b50118e9ddb795890eb1f13684,111.2397,144.0514,104,10.2537
+72ed4046708e5607eb0a5703905438ee,184.7243,109.1889,47,36.3905
+73280f6a624b3bf7a766c70b31dfc56b,0,0,0,-1
+7367ede966b44c6dce30b83345785671,0,0,0,-1
+73b28e2eadad587c9a8ac6c7186dd51b,324.4242,220.0303,110,6.482
+73b28e2eadad587c9a8ac6c7186dd51b,114.5333,376.2,85,8.7404
+73b28e2eadad587c9a8ac6c7186dd51b,300.1961,237.4118,113,8.0582
+73b28e2eadad587c9a8ac6c7186dd51b,194.3889,357.8611,111,6.7703
+73b28e2eadad587c9a8ac6c7186dd51b,0,0,0,-1
+744bb5ab2a706c8070a3f5cd72848ccc,0,0,0,-1
+7471f583e1fb0e34d9e582c313af4358,0,0,0,-1
+74797049e8df8ed38947fd38840b539d,0,0,0,-1
+748bc72733efdabb4c239afb612bf7d5,0,0,0,-1
+74b3ef4c2125d636980a19754702dbb9,0,0,0,-1
+74b542d34b61740c1933d2c953403aa6,173.787,228.4733,89,18.047
+74b542d34b61740c1933d2c953403aa6,86.2687,301.3881,70,9.2362
+74b68f9442209bace31aa62027fbb79a,0,0,0,-1
+750680cce371800ea26576b694b32dc8,70.9085,309.8191,124,23.362
+750680cce371800ea26576b694b32dc8,327.2503,423.9766,94,11.7607
+750c11a0a87833e0bb26441b52b51399,0,0,0,-1
+750ed950a05e5fae10b4d25ed9bcd021,0,0,0,-1
+7525f0ec0999007a0bac946e346eba39,0,0,0,-1
+7577cbd6961b0cab27f88727dcd2d6d3,0,0,0,-1
+762d3d698144370d197a7b9bc978d6c9,0,0,0,-1
+76a77d945cd4c568f3b602957e1ec031,0,0,0,-1
+76e54792d7f5543f734e0906ea8f36c5,0,0,0,-2
+76f36ea4858c572b425eb915e1b27c8d,0,0,0,-1
+77941d758eae521a00ef225e306eda08,368.265,202.4973,132,17.8255
+77941d758eae521a00ef225e306eda08,226.1579,203.2237,114,9.837
+77941d758eae521a00ef225e306eda08,177.2049,263.6776,99,11.8004
+77941d758eae521a00ef225e306eda08,187.4586,327.5921,88,10.4344
+77941d758eae521a00ef225e306eda08,219.9286,361.771,75,12.97
+77941d758eae521a00ef225e306eda08,408.2543,334.0861,74,14.6292
+77941d758eae521a00ef225e306eda08,66.8071,281.7924,72,12.3044
+77941d758eae521a00ef225e306eda08,67.8324,255.1328,66,18.0987
+7797bfd33eb9f06da2b2f5d5c6501af4,0,0,0,-1
+781cf9cc66e59f4586d9338630b95c1a,0,0,0,-1
+7852cb521d7029ca08133476054e7bec,0,0,0,-1
+787bd094dd0586ea0f51f9f8557424a8,0,0,0,-1
+7921bbb92d5390784f3ba046be0d59a3,0,0,0,-1
+797d6bffdecfc88e990e820dc5771a0b,408.3231,155.8,52,9.0973
+79eb6f0a80841d6618968362dfb1f57f,351.5174,367.5814,54,18.4693
+7a705cc36536145911a2ef9ace7d9930,164.7945,140.1438,58,13.6343
+7a82802a862a267d58aa2171645f1181,0,0,0,-1
+7ae953bb9e0356d2990ee6655c8bd168,0,0,0,-1
+7b24367c58f1737e901dde9a934d1eb1,0,0,0,-1
+7b43882369098df840e51421e6059aea,308.604,352.396,204,11.3401
+7b4d476d9414c9339269efe47840d2da,0,0,0,-1
+7b547c5afa0c028b0e20e9a28eaeaa41,0,0,0,-1
+7b6c63074678f65784bdc54d8d385b83,0,0,0,-1
+7b72b604e0af8decb22021cdb92927ae,379.5441,393.8992,116,24.2742
+7b76426f64cb4fbe3d4caa1dcbf47a2f,0,0,0,-1
+7b84056d69644df2a9452a1746d14d39,0,0,0,-1
+7b87e500ff88c264aceb67cf57b32d6d,0,0,0,-2
+7bc437435c5677d361177adb80547bd0,0,0,0,-1
+7bcecfdddd3bd47e3b36ffb05bbdab60,0,0,0,-1
+7bd3565827be855caf938e72b3a7880a,219.245,259.5761,86,10.2537
+7c8aa548b813dadf972c38e806320179,0,0,0,-1
+7dbc5207b9ec1a1921cc2f03f9b37684,0,0,0,-1
+7dc59759253943ac070ab2557c219731,0,0,0,-1
+7df28e2253be3490208ba9a9f470ea1d,0,0,0,-1
+7eb217c0444e5d866bd462ade5266a06,0,0,0,-1
+7ec258e536a1e0353375295ad1b71e5b,153.9063,280.8281,110,9.027
+7ec258e536a1e0353375295ad1b71e5b,276.6656,343.998,80,9.953
+7f45518a2f938a92fa99658d98770316,0,0,0,-1
+7f524231183ed193b8f2e3d9cc73c059,0,0,0,-1
+7faa456389e1ffde464819d0b1360188,416.4381,341.2762,134,11.5624
+80588b9231bb4fb7e1cddc9321d12e76,0,0,0,-1
+809ae218d8b4a973d11358264e4a0823,0,0,0,-1
+80e01dfd642c5aea680852498ddabd28,0,0,0,-1
+81528d5c9ea936264bf9aa8ab4f0ea5d,154.4974,354.4031,104,15.5945
+820245d8b211808bd18e78ff5be16fdb,0,0,0,-1
+820cc2a44d87d9b3798782f7cc6f2a74,0,0,0,-1
+82289d2db2b1e33d68ba6736b21b0e43,354.9352,242.1449,87,12.5488
+8269e2eb69b3ba38c48dd5ae6039e250,208.1649,377.2784,73,11.1132
+82df9b029653e867e86ce9e86ca7275c,0,0,0,-1
+83463d2951670b7e8c3efd7594a13e10,410.6469,129.6963,67,28.5552
+834dd009c49e7faaf8e4caba668a2d8f,0,0,0,-1
+84402e42c992259ac8cdd98b51d4fba3,0,0,0,-1
+844032970cb66839f748512acba0be8e,0,0,0,-1
+85059119462b510aacb6da54983addcf,0,0,0,-1
+85746d90494345e38ab61533e999b3f1,344.6816,303.6669,143,16.0167
+8589428b683d33b99557d7d3b43a518c,0,0,0,-1
+8615d91dab90b906088e4097fc822820,0,0,0,-1
+862d1d80391d146b2cd02478a798b365,0,0,0,-1
+86515f063b3a30af09ba4d0322edf7b1,0,0,0,-1
+86ff28a92989348192783795a5b442e5,109.8725,172.4199,97,8.7541
+87b81bd007c5b23cd0c0aeca722fe52f,0,0,0,-1
+88be713eb83cec7d31c4553ca05b2019,0,0,0,-1
+89629540f3b3cbc2a18d9919facd34d0,0,0,0,-1
+89960d9a801625bf76e9e1047acc5cd5,0,0,0,-1
+89fbce8f7fe8ecc1bf7067a292c7ab2d,308.4718,178.1694,108,17.7697
+8a17bbe3cc0079c6d7d7579359bcf565,0,0,0,-1
+8a1fa06a0099522730dd3c12c9b9cc78,144.4186,131.093,62,7.3993
+8a2de07f6e9dbb8c6e4bfad7e83b3f0a,0,0,0,-1
+8a8419bb3048294f69a31de36cd35a98,251.715,166.9513,155,23.4916
+8aaa3a09b1f20e950609a62a1de511df,0,0,0,-1
+8ad1af382994ce945a5034fab202d402,0,0,0,-1
+8c22afe3214768d4c585580a2364614d,338.025,373.7625,36,10.0925
+8c2f9e7025d6070e9f4ab8a65c8e9dbb,0,0,0,-1
+8c4d81d9d24d9d66e9ced5f40d07960a,0,0,0,-1
+8c5288b86ffcd597f10d639e9948411d,105.0874,206.257,118,26.9385
+8c6f2ce60479f73c257173911aff3453,0,0,0,-2
+8c7b03ed7f61c7faa5a26e126d769404,296.4893,377.8351,36,21.8852
+8c9925cf3627cd4742bbc8677f905afc,0,0,0,-1
+8cb4c49a88d8ecb99d97cf5d707d58d7,0,0,0,-1
+8d5c4cc78e964463699c19003be70851,0,0,0,-1
+8d98bf96ed8555da4df44f26cc8426bf,0,0,0,-1
+8e0624a689e8e02dbae149771f51f8ca,0,0,0,-1
+8e7638040431e1d91dffa4497f7078d9,97.2263,277.6909,44,23.4916
+8f0c4220a437192a30ae06d82bf78885,0,0,0,-1
+8f0d9699a15acef00da458eceaf0c846,0,0,0,-1
+8f28d220d960b67f799479f319373c21,0,0,0,-1
+8f4c97d428c70831d74660bca08961b9,366.2316,257.7684,124,26.9397
+8f6e50767b3bc4367bfe551b0ed73773,0,0,0,-1
+90604d9cce6ab054664c8efa7ce61b20,0,0,0,-1
+90d6324d7006a3d142ee1884279dcf9b,0,0,0,-1
+9109609020945cfc237125dc5f43f7b9,0,0,0,-1
+9139a5b2f18c79a75c2d8ee817cc2495,0,0,0,-1
+916ab7b22affc5651abfc9aae01bb355,0,0,0,-1
+919b9f74bcee297abd6e217d185a025d,0,0,0,-1
+91d0606b85ab7dbc7bab718c1312f2df,0,0,0,-1
+91ee390b30927af8804d1f2adf2aefa8,378.4952,381.1619,134,11.5624
+92286959d1899e9b480d29c545cb1e0f,0,0,0,-1
+92d5f6230c3b6f6256e57d30981c1aaf,0,0,0,-1
+933cc0dec1c737d9654820453ce64284,369.2904,315.2877,87,21.8852
+934bc93ae41ee1d98c7c44d483327f8d,0,0,0,-1
+934f01786c3bdf8eeaf7d8411a3a8f82,0,0,0,-1
+935908ab6e4c329756638887f2dedca2,0,0,0,-1
+93b60dbb5cc3fa4c4cc9247cb1143a09,0,0,0,-1
+9437f7c26ffdaca5a9ae5302d9736c35,0,0,0,-1
+9462c59a652187dc2d581b8772bcb3f0,0,0,0,-1
+94cd77da118cc1d667cd9732853f0c48,0,0,0,-1
+9560214767e1257dc97c5103a27f1d2c,214.8017,207.2824,73,8.2314
+9560214767e1257dc97c5103a27f1d2c,72.6175,274.273,54,6.8699
+9560214767e1257dc97c5103a27f1d2c,115.3411,219.9286,58,9.1966
+9560214767e1257dc97c5103a27f1d2c,343.998,423.9766,49,9.2977
+9560214767e1257dc97c5103a27f1d2c,97.3684,264.7193,69,8.5191
+9560214767e1257dc97c5103a27f1d2c,66.8071,296.8311,49,8.6467
+9560214767e1257dc97c5103a27f1d2c,303.3251,379.8858,43,4.158
+9569bb8d5fc4461461078b2e2ca29f1f,0,0,0,-1
+95edad4544e59e37188dd33db40cecb7,0,0,0,-1
+9626af3a0a37c4fa5187447f01aa69da,0,0,0,-1
+965fbaad39ecdaf8a135f022c8ddaef3,314.2623,343.6562,98,22.8462
+968808e60982c76366088b4db7254671,0,0,0,-1
+96dce4424dce5451ab0a068c58435c1b,0,0,0,-1
+96fdfdfc4417d5bf8e6750edbac8ff90,0,0,0,-1
+9759889dcee7ed0043d06e03fb44060d,0,0,0,-1
+9759a365f7a8b828e964b0a53cc2daf8,0,0,0,-1
+975c90ab2afd216efbb6b772a22ba3d9,0,0,0,-1
+975f7f3c5bad9e9f0bc31e723fd6f793,66.1235,336.1368,72,27.893
+97967da068bd4ee2d9cb7558f1d8c18c,0,0,0,-1
+9842a3b9dfabab4ae8642d9953058ce4,0,0,0,-1
+98bde8f061ae92dd23b0708fdf41381e,0,0,0,-1
+98ea0b7d586e5e888e31633772f4df94,0,0,0,-1
+990fbe3f0a1b53878669967b9afd1441,0,0,0,-2
+991a2fe88aeb9ef23bb011e3843c9105,0,0,0,-1
+99579bbe92d0bb4d5cd98982305870af,0,0,0,-1
+99ce8aa6c0afe0e418f49823f8639776,441.0661,195.6615,78,27.3517
+9a5c2aa17362a58ae8adcb4e0a46c7e0,377,225,282,6.8637
+9b259149a750af0c21640624e4be964a,0,0,0,-2
+9b4f0020e407fd7f980f4241fb6ac7ce,0,0,0,-1
+9b797e680158d10e5ae2f9166c1dabb4,0,0,0,-1
+9ba5fbcccfbc9e08edcfe2258ddf7178,0,0,0,-1
+9bf3ca649999bc6856ad9f01c64eb7e4,0,0,0,-1
+9ce92cb785c9878389bd5f765a07e1ae,0,0,0,-1
+9d44fcc8ab801ac9244da4c016d0541e,381.5556,149.7071,130,11.2272
+9d453de54a141820fcf62bed9a53540d,0,0,0,-2
+9d89b32f7dea356b2d35cead7bc94d80,0,0,0,-1
+9db8f95c3240b79c32af0c0bd367dd91,0,0,0,-1
+9e249726076fa41af6766e12957a7e9d,0,0,0,-1
+9e471e15d44721a48d8b5f4b0a160dd6,213.7764,402.4439,100,10.3444
+9e680611b54f8fad7acf818b15385002,420.9005,364.5053,181,8.6467
+9e680611b54f8fad7acf818b15385002,93.1248,429.1035,110,8.9128
+9f12d2d6134af032932ed37776c6d09f,0,0,0,-1
+9f19c381184ba62416025849c464630e,92.4413,287.261,91,26.9732
+9f49140c0447a0c3108ba3591b11958f,0,0,0,-1
+9f73628a5e06cfc6723f3ee2ae4b96c4,296.4893,107.8218,148,22.2662
+9fc639cbbd749117de4980420ae52cf3,0,0,0,-1
+a01074fefbae0234398c365adf970118,0,0,0,-1
+a0cdb677841933136fd15257e3c47fe6,0,0,0,-1
+a187b24f9827de759fb86a84e9b2e544,345.7143,168.7293,79,13.0131
+a1b021261acaa7ffedfe15d2c8380de1,0,0,0,-1
+a26bba2936f12f19893e54b40e0759fe,0,0,0,-1
+a2c59fd551d9c658f8469726b66bee87,0,0,0,-1
+a2f41e283f3c797e85c0b9d63453b365,0,0,0,-1
+a2fc15125f7e222b3d8d579167f4fc95,0,0,0,-2
+a2fe50d59500281851fce256e922b675,0,0,0,-2
+a305389fe87d54597dfad222e47abac5,0,0,0,-1
+a3cb12d3b8d5c64fa55f27208fe13a07,0,0,0,-1
+a4ae73433e63549558a3d0eed9128a69,0,0,0,-1
+a4ebf3e2861b7845845bad3bacbbaeb5,0,0,0,-1
+a4fa7dd73e3017b97ac6674a10fac216,0,0,0,-1
+a590753c175011e42bf17b90e3aec3b0,0,0,0,-1
+a59b1dc7e417fea605b34a5204f61f9d,0,0,0,-2
+a6195eb9162fc40d5fa2fdb1239dd788,0,0,0,-1
+a647d0ce63b01c9ee82fe1911ba7b1e5,0,0,0,-1
+a654285bc604830f627687fa821d7dd3,0,0,0,-1
+a6b7aa6b98dd87cf75a5e1f707369832,0,0,0,-1
+a6efbb642c60022fe194da17d71a7fb3,373.0501,166.2677,139,11.0224
+a6efbb642c60022fe194da17d71a7fb3,142.6842,141.6589,94,13.6716
+a6f09ff7b85c72ee28a9e725bb1ec652,0,0,0,-1
+a7293f9b20e715fc78cc0b09a4feab01,0,0,0,-1
+a73f098ed638571f8db71a20e1551875,0,0,0,-1
+a7411bdc623413af46a30bd9d2c41066,0,0,0,-1
+a79023a82079a7431ef2496acbef29de,0,0,0,-1
+a7eca254c634f5f6e3cd0e508b069f1c,0,0,0,-1
+a83542b34be44586e8c9f96f4fa180da,0,0,0,-1
+a858e3c7cf53e0996d76f57f2210c59c,0,0,0,-1
+a87740afc072074e6c5a2ab787235dde,101.6696,234.9673,90,20.5187
+a8d308b966048be67f7413daf952ee94,346.9312,190.6714,70,14.1054
+a8f2ebe1d66b24741cac1eb465a2ff72,0,0,0,-1
+a906cd7c6ad05c27216125485d2b7322,0,0,0,-1
+a93362de52065e73e6882f0cb668d637,0,0,0,-1
+a998534bc46d3041e00c67f44a3e0352,0,0,0,-1
+a9c1d12dabcd5f5b13d2aad47e443684,0,0,0,-1
+aa198aacdec142168b8de04c4444054e,0,0,0,-1
+aa477f5b9ce7ab1e886e474be5397727,0,0,0,-1
+aa528ce110f888679a4027513aeb442b,113.539,357.2377,114,9.885
+aadd54d387e9be8fab53507c4cedf338,135.9118,335.6275,147,11.3961
+aaeb75b838690ba6ba425f73b9773479,415.277,325.3176,48,19.4134
+ab5de6c17f4086ba09b7145178d83b45,0,0,0,-1
+ab9e5f1718f2af09030dd33b531f066c,0,0,0,-1
+abc4cfb4ac045b4f9a74e2dbb18f8193,70.0515,286.0515,75,11.1132
+ac4e4bd5633dd74c99762acdba21934f,0,0,0,-1
+acbb4e34904af9781fe089f586418a21,0,0,0,-1
+ad5f3a8ee73c1ff4cf401746be3bd493,0,0,0,-1
+ad914d487aae66bcc2a7760a959d8a7c,0,0,0,-1
+ae42429e25ce48034baa3dd527c7810a,0,0,0,-1
+af2b9f7d489ffab8e3590658853cacf8,0,0,0,-1
+af3657cf479490d027ada92b330f80af,0,0,0,-1
+af7420c5b1c47763ecb5f6e286517b2e,0,0,0,-1
+afc15e047f3e127871d13e39cde7557d,332.4493,354.7681,109,29.6401
+b06ccf39536d0e3e0e8c78ba599ed23b,0,0,0,-1
+b0864a9fd01ec7c7fa3a8301bdb2d03d,0,0,0,-1
+b0d5ba3a5ac7998791f7e484c070dcb9,0,0,0,-1
+b1184cbc6dfa46734807211f95f3c998,0,0,0,-1
+b1786f35f31c424f6c9e3380c1c51c0b,0,0,0,-1
+b227e1ab3efc4b3c5148a614d01edf50,0,0,0,-1
+b280f1f464aa5e0de843229de12fc1aa,0,0,0,-1
+b2d6eb577e716ade61ca89b6bb3dcabb,0,0,0,-1
+b2f99ba5baa498246add63b1acf62cd4,359.5649,358.2351,115,11.3234
+b3854df98b8325a98f7b48bbaf24bb02,0,0,0,-1
+b3c2d92976acd67a13493cdff1ec33ce,0,0,0,-1
+b3f57de0b4ad4dfae87698ef8fc67e23,0,0,0,-1
+b42263b9b84f10464a94092e0cdc13b1,0,0,0,-1
+b4581f4f4cad292b5a013d35d1c39f24,0,0,0,-1
+b4d7268f5a8436da6634e585db3e9478,0,0,0,-1
+b51f22a84cd2fae1de8bd1eb155933f7,188.9516,378.208,55,21.1402
+b53168fc0e9800e06de66f53daf9c5f9,0,0,0,-1
+b5c041f7d841532ef778fd5e71309cc2,0,0,0,-1
+b61b1911d3631bee521fcda3a3e568a1,0,0,0,-2
+b818f0244d2adb13520191eed99e4680,0,0,0,-1
+b8276dbece0182602d2ae0c825dfa1b4,0,0,0,-1
+b844a9510fc4021d9603cdf24cf0545b,0,0,0,-1
+b887defbf88deb3c6fe4c22405d0a957,0,0,0,-1
+b8ad1b45ae4ba6c97951ed30b8640f6b,0,0,0,-1
+b921bb8f821ccab27ab69ea94b8149a7,0,0,0,-1
+b947a27711c94dda2d13e7410285cc0c,0,0,0,-1
+b997943f8b95d72ca9a3c36f5c695412,0,0,0,-1
+ba05599872742ce748e2eda745e51857,0,0,0,-1
+ba162711fc958842582ef1828d37f8e0,0,0,0,-1
+baafc60a08ae90052fd44eb78a21cfbf,0,0,0,-2
+baf842dd446ce9d7082efe16d22fb971,84.6143,381.8403,43,32.926
+bb0a8375885408a7adbd7c941098548f,0,0,0,-1
+bb8393e219a2d5e3f8a183da638cc210,0,0,0,-1
+bba773fb9c1c517e23efe05e283b58a2,0,0,0,-1
+bbed0d350caad0e19e5b0fc858097ce4,0,0,0,-1
+bbf958c2331a553d5699a1369b7f2bbf,0,0,0,-1
+bc28807c545959c0e6e2708067201caa,0,0,0,-1
+bc43e8a2cb05a45e73dea8c7e02f2cc1,0,0,0,-1
+bc848c4d50c2f72fdcc1102475b56525,0,0,0,-1
+bca9f24f465ae61a03e35a1f682270bd,0,0,0,-1
+bcb416e94f3505c120a54dbfc0d5a234,0,0,0,-1
+bcc701884a32d8883b73b5844241a354,370.2039,260.4896,275,18.5468
+bcc701884a32d8883b73b5844241a354,151.4403,376.5208,165,13.6433
+bcc701884a32d8883b73b5844241a354,140.4688,145.7883,128,12.546
+bcc701884a32d8883b73b5844241a354,224.2506,262.4844,96,19.4202
+bccbc10909a55c0f654719e8839f530a,0,0,0,-1
+bd702368c252929cf701ad56ce64b6e1,0,0,0,-1
+bd87def5b7e1ec4f0057cde049995d83,82.1026,197.7179,60,9.9656
+bdb59c956d48bc1a263acf997926c4d3,0,0,0,-1
+be024b0b5cf93c597758e65f348475af,0,0,0,-1
+be57c648eb683a31e8499e278a89c5a0,72.9779,328.6455,95,15.5231
+beb2f21fa785f088469a4530784e9d81,441.8419,206.3088,86,18.6097
+bedec8e1ad130a08faeec8ed81780d56,0,0,0,-1
+bf1c730d11f5c1db7da7c39808451c4c,125.5078,338.9519,39,17.6678
+bf3dbf9b2379ca92ceaafc1867de0422,0,0,0,-1
+bf56e271a2aa37625192954157e9f64d,127.0182,207.8727,175,11.8345
+bfb3e2d11c149036bbe12566ef6b933c,0,0,0,-1
+bfdf6f821031435d9a397afe001ad774,306.7026,334.6299,121,13.2987
+bfdf6f821031435d9a397afe001ad774,160.4169,187.0143,115,8.4108
+bfdf6f821031435d9a397afe001ad774,384.8523,232.7273,116,10.5851
+bfdf6f821031435d9a397afe001ad774,155.3586,332.7448,95,13.5875
+bfdf6f821031435d9a397afe001ad774,87.274,292.4065,118,11.9873
+bfdf6f821031435d9a397afe001ad774,89.2688,278.4429,111,10.6597
+bfdf6f821031435d9a397afe001ad774,364.2195,269.1338,133,11.0066
+bfdf6f821031435d9a397afe001ad774,196.3234,352.5831,105,16.0138
+bfdf6f821031435d9a397afe001ad774,175.0455,364.5519,107,13.0977
+bfdf6f821031435d9a397afe001ad774,124.5104,317.0091,97,7.7829
+bfdf6f821031435d9a397afe001ad774,426.7234,301.0506,90,10.344
+bfdf6f821031435d9a397afe001ad774,136.8542,336.4653,91,13.5406
+bfdf6f821031435d9a397afe001ad774,135.8143,372.1987,91,9.5204
+c004a9415539a0bc98c42c1a444cedb8,58.0169,281.1026,28,21.9429
+c0279b938ac1790f1badfcd4459f5c4c,0,0,0,-1
+c02daa2116b27ce9b023fe7809ef5be9,0,0,0,-1
+c0712bc73239d89cddd71a93865e2946,0,0,0,-1
+c0a71c28edac0a4bbdf64f058903c4b4,0,0,0,-1
+c0f2e3b499d10d147892579d0ad71321,0,0,0,-1
+c14816a1a9a6852c6b0d88fe5585c8bb,0,0,0,-1
+c187d7be84f64e29e6623c15575f373f,0,0,0,-1
+c19197af81f94110ddc23317e182f37d,143.1286,348.926,187,42.789
+c1ac4b0949e6e7557f82caf20761322d,0,0,0,-1
+c1f5ca42b0e336a7ab85b4c437b382c0,0,0,0,-1
+c24798432bb6a0d4c80df831b8e09246,0,0,0,-1
+c24dfc6534bc563d5aecb1513fea8f7f,81.6221,265.4766,41,3.3247
+c24dfc6534bc563d5aecb1513fea8f7f,82.6195,254.8377,32,6.781
+c278a6dc82c323254ff53c58db759908,0,0,0,-1
+c2878958469b61d4f4406bbe945f8bd7,0,0,0,-1
+c2af7c1d6159ae152a79f32d88c33ab2,0,0,0,-1
+c313167b76fb2528816d40088ba88c77,370.2039,308.3649,77,11.7827
+c31e3540b227a1a2b08593094609ece2,0,0,0,-1
+c3d37bdb061c189269f4223f8bebeae0,119.6591,265.1705,95,18.334
+c3e23e84b9f9f31c3ba5458c7f43ec52,466.6195,198.6506,29,8.6697
+c3e6b43c5ac3f4ac052e0b0421f5b088,0,0,0,-1
+c51d53068736c39d56b99074d2e29e12,0,0,0,-1
+c545ccf3a5128fdc313ed936f61658a6,0,0,0,-1
+c590651cdf70258ffb1b6ee18da6a1b2,168.7286,166.0688,47,6.0212
+c5f73cf44d785e5ac2e7f0a8897f683c,0,0,0,-1
+c6269c87a7571330961e5c4a9f692c10,170.0584,247.5234,110,4.6545
+c645eb8b7b7225457e61cf511a8e46e5,0,0,0,-1
+c65cc99faea7d0f79c175460c712f375,0,0,0,-1
+c68ec9a72b87f4bb7935534182145733,0,0,0,-1
+c690f27c439a58684910d04d6409cd17,0,0,0,-1
+c6b722b00948587dd89a548f9639f447,0,0,0,-1
+c6ba816fd9c99c11ceb189ac24d2d2f6,0,0,0,-1
+c713ec80637677965806579fce0b7dca,0,0,0,-1
+c7b20bdbf5f057ec1e9706ca43bf9a2f,346.2662,367.8766,47,20.613
+c82d5bc4554358b1512f9f871822705b,0,0,0,-1
+c84e28d37dcc14a268b760bf16213cfa,0,0,0,-1
+c8594cc837b12c612d8b9a0913240f8a,0,0,0,-1
+c8a82a4e7e76702f5f10ece6508f2bbe,0,0,0,-1
+c979fbec565e769de7e66944ab5365a4,0,0,0,-1
+c98675ecb5bdc7eb35c69d730da05df1,0,0,0,-1
+c98fb8f387c0979531e11de53607de92,0,0,0,-1
+ca3cdb2e771df9989df5a9cb0296c44c,140.4688,338.287,82,7.4342
+ca3cdb2e771df9989df5a9cb0296c44c,109.2169,166.0688,77,5.3609
+ca3cdb2e771df9989df5a9cb0296c44c,77.9649,137.4766,49,8.6442
+ca4e1486c548679a9c682b6fa1a779d9,0,0,0,-1
+caddd8f856b110ed9bb52872e003193f,0,0,0,-1
+caf38dcf62fe3a05fac40055920d7058,0,0,0,-1
+caf5e9cd994c3c90727d274dd790133a,0,0,0,-1
+caf9672e7177c141dd3d9c8631af6b8d,0,0,0,-1
+cb0110b3780d2cf1134221404b82713a,0,0,0,-1
+cb8d3452b667596fbf132d2ce9ebd0e6,160.1339,368.4409,112,12.7162
+cbf5f53f3648de7d1324257caa40bb90,0,0,0,-1
+cc1bf5250466173086887675dff499c3,384.1675,361.2273,29,4.6545
+cc24c86f88a9d17c04255a4d264030e6,0,0,0,-1
+cc31a959bf4c2a6de3a67dfa378a261c,0,0,0,-1
+cca8f8cc51b58df2a4804a7aee8eef8c,104.2299,137.8091,82,4.2577
+cceb1ae43615e5f144e31d1d1ebbdf90,0,0,0,-1
+ccff3e86a50624e30c22d674f3b0f9aa,0,0,0,-1
+ce0609052ba7b533e2974728b0c76bfe,0,0,0,-1
+ce8b0816304e079bb99c6c25b4fa4b88,0,0,0,-1
+cec6819833f63e96fc3e17e29c0124f8,0,0,0,-1
+ced4f41abff9290b0638b0a25cd5a26d,0,0,0,-1
+cf3034c8828df3c2c23fa697ffde07fa,416.7494,269.4662,94,24.6026
+cf34926681dbf1129cb0a629fb72681b,0,0,0,-1
+cff7e7e9f8cb7b37c109ed6b1f11b783,0,0,0,-1
+d00ee8f03fb00562b2db35e90536ffc1,432.1695,296.0339,151,8.6672
+d08383958039c53ea3347ce1719be43e,0,0,0,-1
+d0baf38ff8d974e7b59c23fd43713de9,0,0,0,-1
+d0c1c175814c610bc333080152a605f7,0,0,0,-1
+d0c86e0c3b3fe3e1dd936b7553ecc29c,0,0,0,-1
+d104e584e51830ea51ee60e69186f83b,0,0,0,-1
+d13d9be7873c99a9fde9d24a95f1590d,0,0,0,-1
+d2282b0eb61b8d3b090cf8eb76776529,0,0,0,-1
+d2285c33945ab3421d753b4fc59ac3ce,0,0,0,-1
+d287819450e57ae8c883ed31dc4dc3a3,0,0,0,-1
+d2a17180c72ce7e5e9cb3870ba7991d2,0,0,0,-1
+d34741458ed4cf1ef6bcf3da21a0c47c,0,0,0,-1
+d36b2cb1cac4b31476c6f86eb1227d3c,0,0,0,-1
+d39d18ec79c7303a61f778f470d439ae,0,0,0,-1
+d3aad463ed33cb02334f0c3029db4587,0,0,0,-1
+d3eaad692dc96b1a1765076716f55421,394.474,370.8688,66,41.9963
+d421129acf503e770dc1575c1b959607,0,0,0,-1
+d4307a302483bcc04717ca4f565db678,101.8493,320.637,72,13.6343
+d4307a302483bcc04717ca4f565db678,150.1104,285.4247,55,14.6437
+d43c9dd1be361b9302c9343af09cc23e,0,0,0,-1
+d4e5c5bf1871b85914168ea12ed579a3,0,0,0,-1
+d51dffd06b80ed003aa6095b0639f511,0,0,0,-1
+d559c9b1f2be30c82f8dbe4d73d67bd2,0,0,0,-2
+d5c43054ba0f66d5017a8ddfde8c8c34,0,0,0,-1
+d66d6279f6a55d7263e2700749b4293b,0,0,0,-1
+d68bfca920fd548909bd9c7eb5694b9d,0,0,0,-1
+d73264d2c4f71ef6bf8593ac55565d93,0,0,0,-1
+d73fda3be1180e4465df6fbef8a0648d,0,0,0,-1
+d74af71db9023b65737ee37ede219422,96.9156,230.9,100,7.0684
+d74af71db9023b65737ee37ede219422,396.4688,414.4221,31,17.0306
+d809c513476775193aba29b31d0050c6,0,0,0,-1
+d81ab3ad896e4198caed105c469a4817,337.6221,384.1675,55,14.354
+d89499632a4c7bde0923003497ffc5ea,445.3416,267.4714,58,10.8244
+d89499632a4c7bde0923003497ffc5ea,65.6636,311.0247,49,13.0639
+d89499632a4c7bde0923003497ffc5ea,65.6636,159.087,48,7.1924
+d8a0ebe575539c2357c2365cdf0229a0,402.8,174.6485,69,14.4943
+d9543b86db1c662ebaa71557e715861c,213.6117,380.8429,91,6.273
+d987c00ec5463a0a696991b72d934512,0,0,0,-1
+d9ef71a00fd504eac1a6dd104c93ce56,152.2217,228.0985,115,16.0769
+d9fb9617188fe99bdb464c126d2bd8c0,0,0,0,-1
+da8fea00d3e921e5d8ab4d90a7f6002f,387.8247,432.7078,61,20.8264
+da8fea00d3e921e5d8ab4d90a7f6002f,389.8195,428.0532,51,20.527
+daaf7680aa9a2b519e53b0e38300163d,99.2619,197.7143,56,7.3127
+daee58dd09c005fe41ca370c2a2fdfa9,0,0,0,-1
+db7c113445db32f9beaf5dc90e7218ad,0,0,0,-1
+dbcb3dbee4f4e75d0672c2a23feb1e3a,0,0,0,-1
+dc1ecce5e7f8a4be9082cb5650fa62bd,0,0,0,-1
+dc5cd907d9de1ed0609832f5bf1fc6e2,0,0,0,-1
+dc66d11755fd073a59743d0df6b62ee2,87.7179,188.359,85,7.0467
+dcde02d4757bb845376fa6dbb0351df6,401.4558,330.9727,69,17.6678
+dcdf0b64b314e08e8f71f3bec9ecb080,0,0,0,-1
+dcf5fd36b9fff9183f63df286bf8eef9,353.913,337.6221,122,5.6812
+dcf75f484b2d2712e5033ba61fd6e2a0,0,0,0,-1
+dd281294b34eb6deb76ef9f38169d50e,0,0,0,-1
+dd571c3949cdae0b59fc0542bb23e06a,0,0,0,-1
+dd5764803d51c71a27707d9db8c84aac,0,0,0,-1
+de04fbf5e6c2389f0d039398bdcda971,0,0,0,-1
+de4d3724030397e71d2ac2ab16df5fba,0,0,0,-1
+de635c85f320131ee743733bb04e65b9,0,0,0,-1
+de881c07adc8d53e52391fac066ccb9f,0,0,0,-2
+de9f65a7a70b73ce2ffef1e4a2613eee,0,0,0,-1
+df1354de25723c9a55e1241d4c40ffe2,0,0,0,-1
+df54dc42705decd3f75ec8fd8040e76e,0,0,0,-1
+df75d5a21b4289e8df6e2d0e135ac48f,0,0,0,-1
+df8614fd49a196123c5b88584dd5dd65,0,0,0,-1
+e127111e994be5f79bb0cea52c9d563e,0,0,0,-1
+e129305f6d074d08cd2de0ebdfeaa576,0,0,0,-2
+e1584618a0c72f124fe618e1ed9b3e55,0,0,0,-1
+e163325ccf00afde107c80dfce2bce80,160.0844,199.3156,123,5.72
+e188bdeea72bb41d980dc2556dc8aafa,0,0,0,-1
+e1c92d3f85a37bd8bb963345b6d66e03,0,0,0,-1
+e1e47812eecd80466cf7f5b0160de446,0,0,0,-1
+e1f3a01e73d706b7e9c30c0a17a4c0b5,0,0,0,-1
+e2a7eaebd0830061e77690aa48f11936,0,0,0,-1
+e2bcbfe1ab0f9ddc5d6234f819cd5df5,0,0,0,-1
+e2ea2f046495909ff89e18e05f710fee,0,0,0,-1
+e3034ac9c2799b9a9cee2111593d9853,0,0,0,-1
+e3a9a6f8d21c6c459728066bcf18c615,0,0,0,-1
+e3e518324e1a85b85f15d9127ed9ea89,397.8898,196.4746,121,12.2573
+e414153d0e52f70cbe27c129911445a0,0,0,0,-1
+e42815372aa308f5943847ad06f529de,0,0,0,-1
+e4421d2d5318845c1cccbc6fa308a96e,0,0,0,-1
+e4436b5914162ff7efea2bdfb71c19ae,0,0,0,-1
+e46973b13a7a6f421430d81fc1dda970,0,0,0,-1
+e4a87107f94e4a8e32b735d18cef1137,0,0,0,-1
+e5438d842118e579a340a78f3c5775cc,0,0,0,-1
+e608c0e6cf3adf3c9939593a3c322ef7,0,0,0,-1
+e6214ef879c6d01ae598161e50e23c0c,0,0,0,-1
+e63f43056330bc418a11208aa3a9e7f0,166,295.5,102,5.7536
+e63f43056330bc418a11208aa3a9e7f0,403.4706,205.9412,102,8.0582
+e63f43056330bc418a11208aa3a9e7f0,70.3182,236.8844,79,4.6545
+e63f43056330bc418a11208aa3a9e7f0,136.3333,259.875,63,5.5279
+e63f43056330bc418a11208aa3a9e7f0,56.0221,294.0688,59,6.781
+e63f43056330bc418a11208aa3a9e7f0,428.5,337.5,60,5.9708
+e63f43056330bc418a11208aa3a9e7f0,151.1852,149.4074,71,5.8632
+e63f43056330bc418a11208aa3a9e7f0,208.5,168,78,4.5135
+e63f43056330bc418a11208aa3a9e7f0,208.4074,333.8148,57,5.8632
+e63f43056330bc418a11208aa3a9e7f0,441.6341,262.0732,50,7.2252
+e6d4a747235bfcc1feac759571c8485c,0,0,0,-1
+e6d8b2631843a24e6761f2723ea30788,0,0,0,-1
+e787e5fd289a9f1f6bba31569b7ad384,0,0,0,-1
+e79f52e833ccca893509f0fdeeb26e9f,0,0,0,-1
+e7cb27a5362a7098e1437bfb1224d2dc,171.0558,379.8455,36,31.1315
+e7d76f0723911280b64f0f83a4990c97,0,0,0,-1
+e8be143b9f5e352f71043b24f79f5a17,219.9286,409.4351,94,15.9861
+e8be143b9f5e352f71043b24f79f5a17,150.4429,156.7597,61,6.273
+e977737394cee9abb19ad07310aae8eb,314.1939,324.2143,186,11.1704
+eacb38abacf1214f3b456b6c9fa78697,0,0,0,-1
+ead64f9269f2200e1d439960a1e069b4,65.3312,256.8325,76,10.7218
+ead64f9269f2200e1d439960a1e069b4,71.6481,289.0818,68,9.9962
+eb8d5136918d6859ca3cc3abafe369ac,0,0,0,-1
+eba18d04b18084ef64be8f22bb7905ca,128.5,260.4896,221,4.0446
+eba4bfb93928d424ff21b5be96b5c09b,0,0,0,-1
+ed83b655a1bbad40a782ad13cf27ce8f,0,0,0,-1
+eda58f4918c4b506cd156702bf8a56a3,167.8406,158.1014,104,9.373
+edad1a7e85b5443e0ae9e654d2adbcba,0,0,0,-1
+edae2e1edd1217d0c9e20eff2a7b2dd8,0,0,0,-1
+edbf53a8478049de1494b213fdf942e6,0,0,0,-1
+ee88217bee233a3bfc971b450e3d8b85,0,0,0,-1
+ee984e8fba88691aac4992fbb14f6e97,0,0,0,-1
+ee9c580272cd02741df7299892602ac7,120.5395,199.5658,103,9.837
+eeb1659b92b00e20bd8b6e7eef6b5c9d,299.3883,243.8662,36,17.9532
+eebd87b91489548bdfc1c76a20999a54,0,0,0,-1
+eed63953a76074dd5ef7360e131f4852,146.4532,388.4896,68,11.2843
+eee8e1b2533abcb73e4b03969a3a5904,0,0,0,-1
+eef0e41b1a96cf8c55723fa6aa2f3dc6,293.0714,132.1571,164,9.9962
+eefc3f380cc72d6fa830972151df01ad,0,0,0,-1
+ef3be197823bfa8c6976ca2621e253d5,0,0,0,-1
+ef6a37afe024d33b4b1bb2fdee054a59,165.0714,373.1961,96,19.0408
+ef8a19fb5314b3222482fa325dd49467,0,0,0,-1
+efd5b9e8cb651e18eba6a9623e36e7be,0,0,0,-1
+f0459473753b99105e9723f122022ad0,0,0,0,-1
+f0f72264cd822301852578cc71288d3c,0,0,0,-1
+f136a3df63637b499704a49fc0e3dfaf,0,0,0,-1
+f207bb8bcccdc76143380849402a4f21,227.9078,263.1494,137,8.6697
+f243bd277f1876a77a0fb18f9092105a,0,0,0,-1
+f27d7bf8df3cf0cd187682fc6860b755,0,0,0,-1
+f2e952758095bc50691ab02f724568d2,300.0532,314.3494,104,5.9844
+f39a1e54d79731e4417aa8159d19b7d4,0,0,0,-1
+f39dacd5f134f3f4482094d3f8a0aff1,194.661,364.5519,130,9.974
+f3d40bbf94a7951dee3b0028e301a126,0,0,0,-1
+f44dd045f6dcb1e477e6d3dc0f29d7e8,0,0,0,-1
+f4bee414210374e68b6746f70b38d461,62.339,319.3364,54,11.9873
+f52bd66210db45189027991781e1162b,0,0,0,-1
+f55f99177e8b4b267c71b4e5fa4116be,0,0,0,-1
+f5630f467acd9aa977b61a3e5780c2eb,0,0,0,-1
+f5713e8c98ef5378ea678fb8d9192e13,0,0,0,-1
+f599c9bb0bd19126e13fba8b63d2de41,0,0,0,-1
+f69c80f898c9dfd8d3595b7ca7b8c66c,0,0,0,-1
+f6a2e171a3be579b564cd855985ab9d1,0,0,0,-1
+f6a9611b3afd5c6a5fb4a718cd2c38c2,0,0,0,-1
+f6bf2c352e3c5b13ae48f077570f3d15,0,0,0,-1
+f73624b8b22774acf9a3e2c748131eac,0,0,0,-1
+f74cbe4dda0f80dd66e15e64563689c6,73.9753,202.9727,66,10.7218
+f77fd9fd7966b346ce8e7efcb96c7c53,0,0,0,-1
+f78944bd1732001a3c62723a8cc19856,421.0714,279.1078,94,16.6765
+f79681d8561b6443a5b95f78f3ea6411,0,0,0,-1
+f7cdd95c94818875ece1175561025038,0,0,0,-1
+f82560aeea0309873716efe3aa71ef0a,0,0,0,-1
+f83c62177ee552891d22df33be12ab07,0,0,0,-1
+f88ed45f3436cb30e494409dae76df5d,403.7831,337.9545,42,19.9923
+f89a08a93f1ceaccb0cba52156fd6f03,0,0,0,-1
+f8ecf6be8ae631c6dd694c9638a02b45,128.1675,284.4273,96,31.3155
+f8ecf6be8ae631c6dd694c9638a02b45,127.5026,237.2169,91,8.6697
+f8ecf6be8ae631c6dd694c9638a02b45,121.1857,219.5961,88,12.0425
+f8ecf6be8ae631c6dd694c9638a02b45,124.3143,180.5143,86,9.4407
+f8ecf6be8ae631c6dd694c9638a02b45,153.4351,240.2091,87,8.9458
+f8ecf6be8ae631c6dd694c9638a02b45,179.3675,338.6195,76,17.3011
+f8ecf6be8ae631c6dd694c9638a02b45,139.8039,377.1857,63,58.3327
+f9ce0c5ded59a58b9d7ca5200e6b1182,0,0,0,-1
+fa744c0374ccc6aaf6711f463a9e5bc2,0,0,0,-1
+fa7bf17071e3234ab1f350341303b174,139.8462,161.9744,76,7.0467
+fa7bf17071e3234ab1f350341303b174,96.85,366.925,76,7.1365
+fa7bf17071e3234ab1f350341303b174,408.4377,363.887,78,5.3195
+fa7bf17071e3234ab1f350341303b174,343.6667,340.7857,70,7.3127
+fa7bf17071e3234ab1f350341303b174,346.5987,289.4143,42,5.3195
+fa9575f64e6881c6b2730f0e225c9573,0,0,0,-1
+fa968673987cfd078d91641294c3bf63,0,0,0,-1
+fac65dbf7b6972049cfd37b5b122ec0b,444.6175,266.5628,72,15.2644
+fb7ae70f05b6441ac4ea7187ce7c45f7,0,0,0,-1
+fb7dfb6aae597d97c2da24179df0fe56,0,0,0,-1
+fbaa8548e6c3753836579c7987d0034d,0,0,0,-1
+fbe0c3d6e4a50ca1c1bd3101515d0ab4,0,0,0,-2
+fc658f9bc12a751a17f16589f9e3619b,0,0,0,-1
+fcdc2d423356d53759a8f602d40785a6,0,0,0,-1
+fd4c2d4738bc25a5c331dbc101f3323a,0,0,0,-1
+fd64b23b8cd8c371c8f76fbb503e4e0e,0,0,0,-1
+fd7c0fb3c0e764357aa58e5f047be614,213.9442,208.6247,98,14.2302
+fdf2a2f5b86aea0da54732056fc7ab48,163.7416,357.5701,33,19.5563
+fdf73dcce35167f3ed952a58f5a6f738,117.6818,188.75,69,7.4848
+fe26fd2bb25112b3c2ca93eb8e34f8ed,0,0,0,-1
+fe5c37e82b412833b8ad0abb57978377,0,0,0,-1
+ff5d8e90500cf324e7b04a2f07cf0399,0,0,0,-1
+ffe02fe7d2223743f7fb455dfaff3842,0,0,0,-2
+666becc9794c25bb8e0e7982be7cb6dc,0,0,0,-1
+799b283083f1b6547d558f063b318e78,0,0,0,-1
+79e7773230a96a6789c2c64ec39312cb,0,0,0,-1
+81affb342fc98aae0201a6c837cfc3bb,0,0,0,-1
+8264a875a465c029f28110c725fec283,360.2299,169.061,220,9.885
+e58cc57cab8a1738041b72b156fedc56,186.3494,125.5078,60,10.7424
+e58cc57cab8a1738041b72b156fedc56,116.8636,202.6403,53,32.3161
diff --git a/training/detector/labels/label_job1.csv b/training/detector/labels/label_job1.csv
new file mode 100644
index 0000000..1339e16
--- /dev/null
+++ b/training/detector/labels/label_job1.csv
@@ -0,0 +1,363 @@
+id,coordx1,coordx1,coordx1,diameter
+0015ceb851d7251b8f399e39779d1e7d,x,x,x,x
+006b96310a37b36cccb2ab48d10b49a3,x,x,x,x
+008464bb8521d09a42985dd8add3d0d2,x,x,x,x
+00edff4f51a893d80dae2d42a7f45ad1,x,x,x,x
+0257df465d9e4150adef13303433ff1e,x,x,x,x
+02801e3bbcc6966cb115a962012c35df,x,x,x,x
+028996723faa7840bb57f57e28275e4c,x,x,x,x
+04a8c47583142181728056310759dea1,x,x,x,x
+05609fdb8fa0895ac8a9be373144dac7,x,x,x,x
+059d8c14b2256a2ba4e38ac511700203,x,x,x,x
+064366faa1a83fdcb18b2538f1717290,x,x,x,x
+0708c00f6117ed977bbe1b462b56848c,x,x,x,x
+07349deeea878c723317a1ce42cc7e58,x,x,x,x
+07bca4290a2530091ce1d5f200d9d526,x,x,x,x
+081f4a90f24ac33c14b61b97969b7f81,x,x,x,x
+09d7c4a3e1076dcfcae2b0a563a28364,x,x,x,x
+0acbebb8d463b4b9ca88cf38431aac69,x,x,x,x
+0c0de3749d4fe175b7a5098b060982a1,x,x,x,x
+0c37613214faddf8701ca41e6d43f56e,x,x,x,x
+0c60f4b87afcb3e2dfa65abbbf3ef2f9,x,x,x,x
+0d06d764d3c07572074d468b4cff954f,x,x,x,x
+0f5ab1976a1b1ef1c2eb1d340b0ce9c4,x,x,x,x
+0ff552aa083ecfabaf1cfd65b0a8e674,x,x,x,x
+118be21b7e0c3058b29a524686391c66,x,x,x,x
+11fe5426ef497bc490b9f1465f1fb25e,x,x,x,x
+12e0e2036f61c8a52ee4471bf813c36a,x,x,x,x
+13bb12b3b27d5a7b4b142503a1ae9e73,x,x,x,x
+1427be78bcf4aba96c5054b697be9b5b,x,x,x,x
+149cc798827099f8bdb97cf702027305,x,x,x,x
+14f713c1ef037f6c531cffdff0e5fb2c,x,x,x,x
+15aa585fb2d3018b295df8619f2d1cf7,x,x,x,x
+169b5bde441e8aa3df2766e2e02cda08,x,x,x,x
+184c61740244f4ce8fb985af9bb3d8e8,x,x,x,x
+184fa4ae2b7ae010625d89f10186f1c5,x,x,x,x
+185bc9d9fa3a58fea90778215c69d35b,x,x,x,x
+198d3ff4979a9a89f78ac4b4a0fe0638,x,x,x,x
+1dab3271160e1380c5a70a1e3ba40cb7,x,x,x,x
+1e0f8048728717064645cb758eb89279,x,x,x,x
+1f49f0c1d7feedcae9024d251797407c,x,x,x,x
+1fb4887efd403cd9c0f6970fc8b679b5,x,x,x,x
+229b8b785f880f61d8dad636c3dc2687,x,x,x,x
+2365e0afe6844e955f3d4c23a16dc1a9,x,x,x,x
+243e69389ae5738d3f89386b0efddbcd,x,x,x,x
+245fe0c86269602b0dab44c345b0b412,x,x,x,x
+2488c5b32e837dc848fe6fe4b1bbb7cb,x,x,x,x
+2619ed1e4eca954af4dcbc4436ef8467,x,x,x,x
+274a81c75d244187247789bd71de2b3a,x,x,x,x
+281bb28a077ccfcd40ce4a543a5aea89,x,x,x,x
+28a9b77a9113ce491433d3ea47fa8fc9,x,x,x,x
+28e29fe26140703e5bbe570f982bd112,x,x,x,x
+2969c7ad0e550fee1f4a68fcb3bbb9e5,x,x,x,x
+29d92a1e253cef2c7f34c6db26ce11e3,x,x,x,x
+2a20e4a4e6411f72374fdffebabfc235,x,x,x,x
+2a2300103f80aadbfac57516d9a95365,x,x,x,x
+2b861ff187c8ff2977d988f3d8b08d87,x,x,x,x
+2c06f5c66f3c79515b7712605dea4400,x,x,x,x
+2d5cd7c1ee9a74a1244ddd6b55ad0446,x,x,x,x
+2d977650e6388d2c45825a77e94437a2,x,x,x,x
+2e8bb42ed99b2bd1d9cd3ffaf5129e4c,x,x,x,x
+2ebb1e8f14802c33f0e4215a7545d70d,x,x,x,x
+2ed8eb4430bf40f5405495a5ec22a76d,x,x,x,x
+2f154a687b94f7b59fec7048cbfb5354,x,x,x,x
+2fc3d8ef26fc7aafad44d5034673dd4c,x,x,x,x
+303b4b8425389134997a38b975c205d3,x,x,x,x
+30b8aa7f5688cab5ff0964f34b715c4d,x,x,x,x
+31136e50b7205e9184227f94cdea0090,x,x,x,x
+318bf8045b625b40825552420abfe1ef,x,x,x,x
+31f35f920a472a1c3eacb565fe027923,x,x,x,x
+322bf0acacba9650fa5656b9613c75c8,x,x,x,x
+3252220375d82c3720d36d757bb17345,x,x,x,x
+3285ba0f447f3091c0c7c061b47c2f62,x,x,x,x
+32cda856b7ec759fd3ebaa363c505e88,x,x,x,x
+33dd6666d9f0338929ecce58bb7c4cc3,x,x,x,x
+3457880b1a66030feb8adaed6da805af,x,x,x,x
+348a53f500ada390ddd00cc47d310b2c,x,x,x,x
+34c0760406297a3c8fd5077fb7cd95b0,x,x,x,x
+352c23fe8a3d0640ea531a6bf223732c,x,x,x,x
+35b9a3e9871499893f76c8e6c648562c,x,x,x,x
+375a52b012066845a2eeb5032a92fc6b,x,x,x,x
+380eb569a5750648434cc8ae8da4a0a9,x,x,x,x
+383c27906392e9ce57f6ab5ef1cb6f62,x,x,x,x
+385f1f49b0c20563177c36b7470f1c46,x,x,x,x
+398208da1bcb6a88e11a7314065f13ff,x,x,x,x
+39ebb8121ea6faec0405a4e8db883b55,x,x,x,x
+3a5bbc2f1f5d6d76a48ba5300105d998,x,x,x,x
+3f6431400c2a07a46386dba3929da45d,x,x,x,x
+4001d754871a8da824b8444e32dc6e0f,x,x,x,x
+40c95c9be0bd7c290534ce374c58bec9,x,x,x,x
+437e42695e7ad0a1cb834e1b3e780516,x,x,x,x
+43f2ef8f53e1aa03bfb6378d0c20a8ac,x,x,x,x
+44988c6efa451e8d496188cb30669d44,x,x,x,x
+4521c94debf37a4dc9f3b70366a21640,x,x,x,x
+48e592418247393234dd658f9112c543,x,x,x,x
+4a782bbc2608288a3ed05e511af6f8bb,x,x,x,x
+4af17bcb31669a9eab0b6ef8e22a8dcf,x,x,x,x
+4baa552f3a11782f39e16b345d401fb8,x,x,x,x
+4cc8af2efef2f41bf70684be25276ce5,x,x,x,x
+4cd70a98baca46b116071b32788d3c2d,x,x,x,x
+4d7df08f074b221eec6311c2617a5ba8,x,x,x,x
+4dbda61d574417c7f25d6e9a8f0749a7,x,x,x,x
+4dcd34bd9b10f96453b63d4f55d1fd44,x,x,x,x
+504e447ad62ea9ebb283873e044b5dd2,x,x,x,x
+51bd5c556c77ecdaf489d8dd9f7a05f1,x,x,x,x
+51fbac477a3639f983904fc4d42b8c15,x,x,x,x
+5267ea7baf6332f29163064aecf6e443,x,x,x,x
+54056288ab97cebc4b0ea33c23f47ff6,x,x,x,x
+5572cc61f851b0d10d6fec913ae722b9,x,x,x,x
+55c01868f1d9c37fa3f174dc3c0d44e8,x,x,x,x
+56462ba8833fc842d16be7e311214404,x,x,x,x
+570ea80b0dcc08f3e8751a6f4b2b1cd5,x,x,x,x
+573a661e2d784f9385a3b78c9757ddad,x,x,x,x
+57822feb6186b788c4e1877123428454,x,x,x,x
+5782e6873c666529c6a66421acb043dc,x,x,x,x
+592c2481f17d6a2cecfe7bbb6a27722c,x,x,x,x
+59fc9d939f05bf3023c1387c1c086520,x,x,x,x
+5ade88428e6463fa212d4c287228e8ed,x,x,x,x
+5b412509bc40a3aeb3b5efef1fdfcfc9,x,x,x,x
+5b642ed9150bac6cbd58a46ed8349afc,x,x,x,x
+5c99ab7172afa78312fe73a3c0dd342f,x,x,x,x
+5e0c8cba8eab51076ac0014049d770c1,x,x,x,x
+5fd33ea74e1ad740a201ae9b3c383fc5,x,x,x,x
+608202eb3c368512e55e9e339a203790,x,x,x,x
+608a7028689c6ab3aea5f116007169b2,x,x,x,x
+60b389fb2f7eeb912586d1a3ccc9dbbc,x,x,x,x
+61630ec628631f7fe3980f869e1a4fbe,x,x,x,x
+6171d57221e26d1f15d3c71fe966ab18,x,x,x,x
+624a34fa8fd36847724e749877343847,x,x,x,x
+627499714e279203bd1294290f8fc542,x,x,x,x
+627836151c555187503dfe472fb15001,x,x,x,x
+63b5be42543c98ac5392f1bfbda085bf,x,x,x,x
+648c99653d512edc1d28dd8e7054ceab,x,x,x,x
+64a5a866461a3b6006efb0075e04dffe,x,x,x,x
+65073aadb60e398d8db1806f5ea2a082,x,x,x,x
+6541df84fd779ba6513a530c128f4e9b,x,x,x,x
+65a380c07d416f78e85545eaaa2916a1,x,x,x,x
+662153a685fb4268361bfbaca5e9ca23,x,x,x,x
+668bb968918c63fad7d65581825b1048,x,x,x,x
+66a92d789e440d3dbef3c69d20e20694,x,x,x,x
+676467220abd8e2104417c5213664ef9,x,x,x,x
+678c5ec1360784e0fe797208069e0bbb,x,x,x,x
+6799964c08ad5ce7740defcd3bd037a6,x,x,x,x
+6857c76be618bb0ddced5f4fecc1695f,x,x,x,x
+6969c031ee0c34053faff3aac9dd2da7,x,x,x,x
+6be677ba1631174397b0c1e26a46af30,x,x,x,x
+6cb2908fd789700db727dd96526bc342,x,x,x,x
+6ee742b62985570a1f3a142eb7e49188,x,x,x,x
+6f43af3f636f37b9695b58378f9265cc,x,x,x,x
+6fd3af9174242c1b393fe4ba515e7a26,x,x,x,x
+713d8136c360ad0f37d6e53b61a7891b,x,x,x,x
+71665cc6a7ee85268ca1da69c94bbaeb,x,x,x,x
+721949894f5309ed4975a67419230a3c,x,x,x,x
+72fd04cf3099b148d9ad361efb988866,x,x,x,x
+733205c5d0bbf19f5c761e0c023bf9a0,x,x,x,x
+7395f64fba89c2463a1b13c400adf876,x,x,x,x
+74b1b748971c474a8023f6406c54b18a,x,x,x,x
+75aef267ad112a21c870b7e2893aaf8a,x,x,x,x
+761aeadb65fb84c8d04978a75b2f684c,x,x,x,x
+763ce10dfdd4662f15de3f5931d5534b,x,x,x,x
+77033e4c1591403d1b1255607a20a983,x,x,x,x
+775c5f8043e72b2284b5885254566271,x,x,x,x
+77d6f5203d46073369d7038b2d58e320,x,x,x,x
+7842c108866fccf9b1b56dca68fc355e,x,x,x,x
+78c0a0104c0428e260cbd9e50eb7eea6,x,x,x,x
+7917af5df3fe5577f912c5168c6307e3,x,x,x,x
+799c0026d66479f7447ed0df5955f051,x,x,x,x
+79e0e507b1cd1d0c8107de4fd6b9e444,x,x,x,x
+7bfba4540956c0b2c5b78b3623a4855d,x,x,x,x
+7c2b72f9e0f5649c22902292febdc89f,x,x,x,x
+7d46ce019d79d13ee9ce8f18e010e71a,x,x,x,x
+7fb1c8ffd78ca4b6869044251add36b4,x,x,x,x
+80600d4a5fee7424d689ba7d0906d50f,x,x,x,x
+817a99e1a60bcf4e37c904d73845ca50,x,x,x,x
+820dd342da11af3a062d1647b3736fdd,x,x,x,x
+823b5f08ce145f837066d2e19dab10c1,x,x,x,x
+8298238a27be6111214a9bc711608181,x,x,x,x
+8326bb56a429c54a744484423a9bd9b5,x,x,x,x
+8369f716ca2d51c934e7f6d44cb156e9,x,x,x,x
+839502f9ff68fd778b435255690f3061,x,x,x,x
+84876a50f52476bcc2a63678257ae8b4,x,x,x,x
+84a6c418d57bfc5214639012998356d4,x,x,x,x
+85d59b470b927e825937ea3483571c6d,x,x,x,x
+8601f5424bcf4cd8e7bc3d649e9995a2,x,x,x,x
+868b024d9fa388b7ddab12ec1c06af38,x,x,x,x
+87cdb87db24528fdb8479220a1854b83,x,x,x,x
+87cdf4626079509e5d6d3c3b6c8bfc2e,x,x,x,x
+880980cc7e88c83b0fea84f078b849e3,x,x,x,x
+8815efa67adb15b2f8cfd49ec992f48e,x,x,x,x
+882107a204c302e27628f85522baea49,x,x,x,x
+88523579f4e325351665753e903cfdf5,x,x,x,x
+88ae66cd575c45ec5bb0f1578e2f1c49,x,x,x,x
+8918c484841c5d0a532fe146e9da61bd,x,x,x,x
+893fbc465b9d8a25569659a2bac154ef,x,x,x,x
+898bd4c517fb9cf94c7d06dae56b0136,x,x,x,x
+89bfbba58ee5cd0e346cdd6ffd3fa3a3,x,x,x,x
+8a97ff581c17a49a3ef97144efde8a19,x,x,x,x
+8b6e16b4e1d1400452956578f8eb97c4,x,x,x,x
+8c63c8ebd684911de92509a8a703d567,x,x,x,x
+8e92c4db434da3b8d4e3cafce3f072fb,x,x,x,x
+8ed68f2dbf103a4bc0fd8708d8c1ac93,x,x,x,x
+8ee6f423ff988d10f2bb383df98c1b2e,x,x,x,x
+90409f7fcfec3581033559f8340e48a9,x,x,x,x
+90e3b396e1c1343a514eb5890833d3d8,x,x,x,x
+90e5f4780b2f05136ff5f776a5cbc2af,x,x,x,x
+91d29bc19205f8eb9a63de5b774a5575,x,x,x,x
+92abfd85dd6afb639e9a8b60aaa08262,x,x,x,x
+9397a41c9e819a92eb5c86e0e652d7c1,x,x,x,x
+93a6f37a72f60498986374f57bfc30c4,x,x,x,x
+95a27273c11db8bfb9fc27b1e64de6bd,x,x,x,x
+9660e4a23b8dd7d5056a622ee3568a41,x,x,x,x
+96acca47671874c41de6023942e10c16,x,x,x,x
+9703fd051751879432975535663150da,x,x,x,x
+9a3174ffe867f602ee82c512a01420ee,x,x,x,x
+9b7524785a9bf40f0651deeb3b05b75f,x,x,x,x
+9c779a4e5e56c77131f8e99d5eacb766,x,x,x,x
+9de4a1ebcdf1cfd8566ed1d9b63cbeb7,x,x,x,x
+9e5c2e760b94b8919691d344cfdbac7f,x,x,x,x
+9e922147900b3984c9345bdda573e882,x,x,x,x
+9e98136d07b953c3362e0a132c8810b6,x,x,x,x
+9f52323d216f89d300612cfac0122d8b,x,x,x,x
+a13d6c5f8f86d74e16c10cf9294bca31,x,x,x,x
+a14e41eea93d7667a87d458d5cb28272,x,x,x,x
+a162d204827e4e89a2e5ba81cc53247a,x,x,x,x
+a19a122fe9a790576b57c6bd5cf9ff5c,x,x,x,x
+a2d9e657a673798f9ebdfec1b361f93a,x,x,x,x
+a32e7fdbc0db97e35aabd7c931a582ea,x,x,x,x
+a4dc34f2731b62f60c6c390a39fe11b2,x,x,x,x
+a532c6f9405e6f3a4229ea6e04b0d975,x,x,x,x
+a70fd23bd8d535ffd42259cb91f4c5ca,x,x,x,x
+a76b682e74918492c1f2ca4c13c29885,x,x,x,x
+a784a51caee14229d46777f2a9770a5f,x,x,x,x
+a853993fd839a0ee61f2ca73c4e497a6,x,x,x,x
+a88c585e7d81744eec091a6f0600bd7b,x,x,x,x
+a8e650f8494e894be06c9cee08702aa9,x,x,x,x
+aa2747369e1a0c724bea611ea7e5ffcf,x,x,x,x
+aa55708fcc8bf27b605bcd2fca0dc991,x,x,x,x
+ac00af80df36484660203d5816d697aa,x,x,x,x
+ac3345a5a05655c6bcce7d0b226a0042,x,x,x,x
+ac366a2168a4d04509693b7e5bcf3cce,x,x,x,x
+ac4c6d832509d4cee3c7ac93a9227075,x,x,x,x
+ac57a379cfea05c07d9befe8b9359495,x,x,x,x
+ac68eb0a3db3de247c26909db4c10569,x,x,x,x
+ac9c16f3f287f0e0b321fb518ac71c75,x,x,x,x
+ad7e6fe9d036ed070df718f95b212a10,x,x,x,x
+adc3bbc63d40f8761c59be10f1e504c3,x,x,x,x
+aea6f1621333074412b9a6acdcda31a9,x,x,x,x
+af4dfdda000c16c4cb77ea236cf1e524,x,x,x,x
+af6d573b8c6804e14e3a7b07a376e593,x,x,x,x
+afb37b10bd304fa2c7b70cfaf1f489ed,x,x,x,x
+b022a1d30d62ef2c1f0902f1a047a845,x,x,x,x
+b158f44c31f4121c865c828ff79fc73d,x,x,x,x
+b17cb533d71d63d548ce47b48b34c23c,x,x,x,x
+b5de57869d863bdc1b84b0194e79a9d3,x,x,x,x
+b635cda3e75b4b7238c18c6a5f1858f6,x,x,x,x
+b6578699374a9954b9a8a9e7da2603b1,x,x,x,x
+b6687898fe385b68d5ae341419ef3fdd,x,x,x,x
+b6d8dd834f2ff1ed7a5154e658460699,x,x,x,x
+b7045ebff6dbb0023087e0399d00b873,x,x,x,x
+b7ef0e864365220b8c8bfb153012d09a,x,x,x,x
+b83ce5267f3fd41c7029b4e56724cd08,x,x,x,x
+b84c43bed6c51182d7536619b747343a,x,x,x,x
+b8bb02d229361a623a4dc57aa0e5c485,x,x,x,x
+b8dc33b670bb078d10954345c3ffbb3a,x,x,x,x
+ba71b330a16e8b4c852f9a8730ee33b9,x,x,x,x
+bb4b43d0dc4d9d2b61150df6556f6490,x,x,x,x
+bbe21f027a1df4b07016b474b48d3f65,x,x,x,x
+bc38f78d1194f57452f6bb5eed453137,x,x,x,x
+bda661b08ad77afb79bd35664861cd62,x,x,x,x
+be2be08151ef4d3aebd3ea4fcd5d364b,x,x,x,x
+c020f5c28fc03aed3c125714f1c3cf2a,x,x,x,x
+c05acf3bd59f5570783138c01b737c3d,x,x,x,x
+c0625c79ef5b37e293b5753d20b00c89,x,x,x,x
+c0f0eb84e70b19544943bed0ea6bd374,x,x,x,x
+c1673993c070080c1d65aca6799c66f8,x,x,x,x
+c1ba619e3b49e0cb7798bd10465c2b29,x,x,x,x
+c2bdfb6ab5192656b397459648221918,x,x,x,x
+c2e546795f1ea2bd7f89ab3b4d13e761,x,x,x,x
+c3b05094939cc128a4593736f05eadec,x,x,x,x
+c3e8db4f544e2d4ecb01c59551eb8ef0,x,x,x,x
+c4c801ae039ba335fa32df7d84e4decb,x,x,x,x
+c5887c21bafb90eb8534e1a632ff2754,x,x,x,x
+c610439ebef643c7fd4b30de8088bb55,x,x,x,x
+c67de8fbbe1e58b464334f93a1dd0447,x,x,x,x
+c67e799bcc1e2635eb9164f6e8cf75f3,x,x,x,x
+c8cfb917b0d619cb4e25f789db4641f8,x,x,x,x
+cb64ff663195832e0b66a9bb17891954,x,x,x,x
+cb94c3f894fc93c1ec0eb436c8564ed3,x,x,x,x
+cd104ad99d5b939b6bdd28b154e28085,x,x,x,x
+cd10ceca9862ba0cc2ffd0ed8c9b055c,x,x,x,x
+cf0a772e90a14d77d664ce9baedf0e5c,x,x,x,x
+cfbcb16fea277226d6771d8b1966397a,x,x,x,x
+d09e4124b97b22ef45692b62b4ca7f03,x,x,x,x
+d244870d213a21efa86e86c951d8c9a2,x,x,x,x
+d2b47d9034d38a410f00dabba9754d91,x,x,x,x
+d2eecd9f13a6d474338045d0c91cffbd,x,x,x,x
+d6d5ed3055d084a6abf0f97af3fe2ff0,x,x,x,x
+d7713d80767cfdaad5e3db537849d8d0,x,x,x,x
+d777a77cc7a2ec2f1eed68799cc9075c,x,x,x,x
+d7aa27d839b1ecb03dbf011af4bcb092,x,x,x,x
+d7e5640b52c8e092ec277febc81478da,x,x,x,x
+d81704ee56c124cc1434640918a3299c,x,x,x,x
+d8ed783494996f55a587270a212f7d5b,x,x,x,x
+d917c781760710015473eee9ce82e051,x,x,x,x
+d92998a73d4654a442e6d6ba15bbb827,x,x,x,x
+d991b1760fb8705de655a1da068f7a6a,x,x,x,x
+d9a2bea7df4a888313374beb142cf9c0,x,x,x,x
+da821546432756d377777d7f4c41ca2f,x,x,x,x
+dbfbc12c7a943a2dc0e34bfd4a636bca,x,x,x,x
+dc9854bcdcc71b690d9806438009001d,x,x,x,x
+df015da931ad5312ee7b24b201b67478,x,x,x,x
+df761dd787bfc439890740ccce934f36,x,x,x,x
+e00832e96709eb85f8e0e608ca02c2b5,x,x,x,x
+e10c2b829c39d4a500c09caf04d461a1,x,x,x,x
+e2b7fe7fbb002029640c0e65e3051888,x,x,x,x
+e3423505ef6b43f03c5d7bde52a5a78c,x,x,x,x
+e38789c5eabb3005bfb82a5298055ba0,x,x,x,x
+e43afa905c8e279f818b2d5104f6762b,x,x,x,x
+e537c91cdfa97d20a39df7ef04a52570,x,x,x,x
+e54b574a7e7c650edc224cbdede9e675,x,x,x,x
+e56b9f25a47a42f4ae4085005c46109c,x,x,x,x
+e572e978c2b50aca781e6302937e5b13,x,x,x,x
+e58b78dc31d80a50285816f4ecd661e3,x,x,x,x
+e5c68cfa0f33540da3098800f0daae2c,x,x,x,x
+e5cf847e616cc2fe94816ffa547d2614,x,x,x,x
+e659f6517c4df17e86d4d87181396ea6,x,x,x,x
+e6b3e750c6c7a70ca512d77defcfe615,x,x,x,x
+e709901da9ba15a95d4a29906edc01dd,x,x,x,x
+e8eb842ee04bbad407f85fe671f24d4f,x,x,x,x
+e9ccf1ce85c39779fafb9ec703c71555,x,x,x,x
+ea7373271a2441b5864df2053c0f5c3e,x,x,x,x
+eaf753dc137e12fd06e96d27f3111043,x,x,x,x
+eb008af181f3791fdce2376cf4773733,x,x,x,x
+ebd601d40a18634b100c92e7db39f585,x,x,x,x
+ed0f3c1619b2becec76ba5df66e1ea56,x,x,x,x
+ed49b57854f5580658fb3510676e03dd,x,x,x,x
+eed4db0cb0576c274de569e98a56a270,x,x,x,x
+f17867cc3e579dc2fc6f0334bc43a91d,x,x,x,x
+f1a64fda219db48bcfb8ad3823ef9fc1,x,x,x,x
+f25c425c827b35fcbaa23f2ed671540b,x,x,x,x
+f29d00ddf6d9846aa600c3f0edf5f952,x,x,x,x
+f2ca85bb9ae82a3d79b9f321f727ac19,x,x,x,x
+f2f23b265b2a3b977cb81fe3193d7c2c,x,x,x,x
+f3eafe72b1e9528116f3c430ab73a2ae,x,x,x,x
+f3f6f40ccb01276d722d52701cab1754,x,x,x,x
+f42a0343e5b5154c6a184fc955d8f20f,x,x,x,x
+f467795ce3b50a771085d79ae8d29ecc,x,x,x,x
+f5717f7cbc08d8bd942cd4c1128e3339,x,x,x,x
+f63f2f63e2619012b4c798fd638c8b8a,x,x,x,x
+f6c9e875d7adfe7add08f43528810f72,x,x,x,x
+f725f46908f16062fd12c141eb47c6a7,x,x,x,x
+f76143416ee2c8e1251f45f108fed468,x,x,x,x
+f7a03adba817f2a2249b9dee0586f4be,x,x,x,x
+f8f66fca04d2e67eacd86ea154827a4c,x,x,x,x
+f938f9022abf7f1072fe9df79db7eccd,x,x,x,x
+fa45178d023325b255a3d4fc3e96cb7d,x,x,x,x
+fb57fc6377fd37bb5d42756c2736586c,x,x,x,x
+fb99a80cbb2f441bb90135bab5b029fe,x,x,x,x
+fbae4d04285789dfa32124c86586dd09,x,x,x,x
+fc545aa2f58509dc6d81ef02130b6906,x,x,x,x
+fd0c2dfe0b0c58330675c3191cef0d5b,x,x,x,x
+fd2dd970bd3d91e5b26d7e57c03f70af,x,x,x,x
+fda187bfb1d6a2ecd4abd862c7f7f94c,x,x,x,x
+fe45462987bacc32dbc7126119999392,x,x,x,x
\ No newline at end of file
diff --git a/training/detector/labels/label_job2.csv b/training/detector/labels/label_job2.csv
new file mode 100644
index 0000000..c753709
--- /dev/null
+++ b/training/detector/labels/label_job2.csv
@@ -0,0 +1,297 @@
+id,coordx1,coordx1,coordx1,diameter
+0015ceb851d7251b8f399e39779d1e7d,0,0,0,0
+006b96310a37b36cccb2ab48d10b49a3,0,0,0,0
+008464bb8521d09a42985dd8add3d0d2,102.7163,296.9362,110,13.3988
+00edff4f51a893d80dae2d42a7f45ad1,0,0,0,0
+0257df465d9e4150adef13303433ff1e,140.1664,368.7945,82,27.9374
+0257df465d9e4150adef13303433ff1e,173.1871,302.7938,87,37.4411
+02801e3bbcc6966cb115a962012c35df,98.5909,254.1364,169,5.2926
+028996723faa7840bb57f57e28275e4c,93.0561,280.715,124,16.5068
+04a8c47583142181728056310759dea1,0,0,0,0
+05609fdb8fa0895ac8a9be373144dac7,120.2647,244,83,6.5795
+05609fdb8fa0895ac8a9be373144dac7,141.2881,320.9492,54,8.6672
+059d8c14b2256a2ba4e38ac511700203,438.093,245.1066,50,25.6318
+059d8c14b2256a2ba4e38ac511700203,216.8115,321.1,108,25.731
+064366faa1a83fdcb18b2538f1717290,152.5961,391.5067,46,65.3738
+0708c00f6117ed977bbe1b462b56848c,355.9606,215.4853,126,8.3161
+07349deeea878c723317a1ce42cc7e58,93.6111,390.25,71,6.7703
+07bca4290a2530091ce1d5f200d9d526,138.241,331.6936,111,29.8982
+081f4a90f24ac33c14b61b97969b7f81,182.9869,343.2775,242,22.054
+081f4a90f24ac33c14b61b97969b7f81,123.956,308.8352,155,10.7641
+09d7c4a3e1076dcfcae2b0a563a28364,317.3385,400.0514,111,49.6006
+0acbebb8d463b4b9ca88cf38431aac69,160.8256,165.3605,130,10.4642
+0acbebb8d463b4b9ca88cf38431aac69,410.3051,349.8084,161,26.3865
+0c0de3749d4fe175b7a5098b060982a1,381.5948,326.9085,104,30.9125
+0c37613214faddf8701ca41e6d43f56e,236.6862,271.1596,125,15.4716
+0c60f4b87afcb3e2dfa65abbbf3ef2f9,120.8097,307.7684,111,23.2818
+0d06d764d3c07572074d468b4cff954f,144.76,372.36,161,5.6419
+0d06d764d3c07572074d468b4cff954f,353.375,328.3125,235,4.5135
+0d06d764d3c07572074d468b4cff954f,341.3,367.3,235,3.5682
+0d06d764d3c07572074d468b4cff954f,285.3571,392.7857,235,4.222
+0d06d764d3c07572074d468b4cff954f,382.3,323.3,225,3.5682
+0d06d764d3c07572074d468b4cff954f,160.22,398.44,191,7.9788
+0d06d764d3c07572074d468b4cff954f,131,307.5,247,4.5135
+0d06d764d3c07572074d468b4cff954f,141.3158,399.1579,173,4.9185
+0d06d764d3c07572074d468b4cff954f,125.3,353.7,238,3.5682
+0d06d764d3c07572074d468b4cff954f,115.8333,371.9333,174,6.1804
+0d06d764d3c07572074d468b4cff954f,187.1667,358.2619,127,7.3127
+0d06d764d3c07572074d468b4cff954f,339,308.1739,352,5.4115
+0f5ab1976a1b1ef1c2eb1d340b0ce9c4,0,0,0,0
+0ff552aa083ecfabaf1cfd65b0a8e674,106.1,207.38,102,7.9788
+0ff552aa083ecfabaf1cfd65b0a8e674,388.7849,301.4372,73,30.1934
+118be21b7e0c3058b29a524686391c66,368.6135,248.8127,65,17.8769
+11fe5426ef497bc490b9f1465f1fb25e,358.3725,432.3987,71,19.7386
+12e0e2036f61c8a52ee4471bf813c36a,184.3311,316.0404,104,30.7574
+13bb12b3b27d5a7b4b142503a1ae9e73,127.9873,396.2917,128,21.2019
+1427be78bcf4aba96c5054b697be9b5b,0,0,0,0
+149cc798827099f8bdb97cf702027305,150.2036,359.7203,98,31.5633
+14f713c1ef037f6c531cffdff0e5fb2c,229.4987,187.4586,97,18.5953
+14f713c1ef037f6c531cffdff0e5fb2c,114.8824,362.5294,100,8.0582
+14f713c1ef037f6c531cffdff0e5fb2c,374.875,339.6667,116,5.5279
+15aa585fb2d3018b295df8619f2d1cf7,135.1649,174.1288,74,60.3449
+169b5bde441e8aa3df2766e2e02cda08,334.644,318.874,156,31.4735
+184c61740244f4ce8fb985af9bb3d8e8,0,0,0,0
+184fa4ae2b7ae010625d89f10186f1c5,0,0,0,0
+185bc9d9fa3a58fea90778215c69d35b,363.48,291.3625,193,16.0022
+198d3ff4979a9a89f78ac4b4a0fe0638,0,0,0,0
+1dab3271160e1380c5a70a1e3ba40cb7,159.0643,328.9201,64,25.5572
+1e0f8048728717064645cb758eb89279,146.9273,219.4606,72,14.4943
+1f49f0c1d7feedcae9024d251797407c,205.5734,349.1248,46,16.9797
+1fb4887efd403cd9c0f6970fc8b679b5,414.4065,269.8298,281,10.4567
+229b8b785f880f61d8dad636c3dc2687,0,0,0,0
+2365e0afe6844e955f3d4c23a16dc1a9,189.1676,201.472,189,22.0129
+243e69389ae5738d3f89386b0efddbcd,205.3811,335.729,105,45.1069
+243e69389ae5738d3f89386b0efddbcd,185.3126,382.481,104,28.9666
+245fe0c86269602b0dab44c345b0b412,85.5558,303.1786,139,23.8833
+245fe0c86269602b0dab44c345b0b412,94.1637,331.0124,148,30.4244
+2488c5b32e837dc848fe6fe4b1bbb7cb,0,0,0,0
+2619ed1e4eca954af4dcbc4436ef8467,156.014,393.8992,124,56.8522
+2619ed1e4eca954af4dcbc4436ef8467,411.3304,288.2864,237,23.5711
+274a81c75d244187247789bd71de2b3a,345.8025,289.6624,173,19.9949
+281bb28a077ccfcd40ce4a543a5aea89,62.3638,167.2931,71,10.0929
+281bb28a077ccfcd40ce4a543a5aea89,112.1,108.7,83,6.1804
+281bb28a077ccfcd40ce4a543a5aea89,401.4565,273.471,111,18.746
+281bb28a077ccfcd40ce4a543a5aea89,181.6241,319.1348,112,13.3988
+28a9b77a9113ce491433d3ea47fa8fc9,214.5743,292.4356,108,16.0373
+28e29fe26140703e5bbe570f982bd112,345.7069,243.512,123,21.224
+2969c7ad0e550fee1f4a68fcb3bbb9e5,456.9437,273.1831,150,16.4682
+29d92a1e253cef2c7f34c6db26ce11e3,129.5,192.875,208,5.5279
+2a20e4a4e6411f72374fdffebabfc235,149.737,364.0069,64,19.1824
+2a2300103f80aadbfac57516d9a95365,0,0,0,0
+2b861ff187c8ff2977d988f3d8b08d87,318.7056,372.3665,105,15.6179
+2c06f5c66f3c79515b7712605dea4400,289.4444,348.8,105,7.5694
+2d5cd7c1ee9a74a1244ddd6b55ad0446,128.3291,312.8952,211,13.0597
+2d977650e6388d2c45825a77e94437a2,354.2517,411.3304,80,15.1316
+2e8bb42ed99b2bd1d9cd3ffaf5129e4c,113.974,252.7403,151,29.1063
+2e8bb42ed99b2bd1d9cd3ffaf5129e4c,376.468,257.5254,177,55.2177
+2ebb1e8f14802c33f0e4215a7545d70d,165.7787,386.291,142,17.6258
+2ed8eb4430bf40f5405495a5ec22a76d,178.7692,303.5934,117,10.7641
+2f154a687b94f7b59fec7048cbfb5354,206.9406,377.8351,88,18.0987
+2fc3d8ef26fc7aafad44d5034673dd4c,319.731,331.6936,67,60.9114
+303b4b8425389134997a38b975c205d3,357.548,322.0339,100,21.2303
+30b8aa7f5688cab5ff0964f34b715c4d,372.0247,364.5053,88,15.7816
+30b8aa7f5688cab5ff0964f34b715c4d,368.8219,436.7945,59,16.6985
+31136e50b7205e9184227f94cdea0090,331.01,352.2009,135,12.4741
+318bf8045b625b40825552420abfe1ef,162.8498,361.0874,122,18.6581
+31f35f920a472a1c3eacb565fe027923,196.0033,308.7937,137,13.4823
+31f35f920a472a1c3eacb565fe027923,412.3558,325.5414,73,10.6997
+31f35f920a472a1c3eacb565fe027923,147.8111,201.472,100,10.634
+322bf0acacba9650fa5656b9613c75c8,374.4172,182.3318,382,12.0937
+322bf0acacba9650fa5656b9613c75c8,83.213,290.3371,260,5.5112
+3252220375d82c3720d36d757bb17345,0,0,0,0
+3285ba0f447f3091c0c7c061b47c2f62,153.2797,388.7724,118,30.7078
+3285ba0f447f3091c0c7c061b47c2f62,120.1194,370.9254,104,13.0619
+3285ba0f447f3091c0c7c061b47c2f62,135.5067,380.2276,70,15.7816
+32cda856b7ec759fd3ebaa363c505e88,135.5067,384.6709,99,30.8899
+33dd6666d9f0338929ecce58bb7c4cc3,165.2423,381.5948,124,17.773
+33dd6666d9f0338929ecce58bb7c4cc3,383.6667,390.825,43,12.3608
+3457880b1a66030feb8adaed6da805af,200.4466,258.2089,419,11.9577
+348a53f500ada390ddd00cc47d310b2c,0,0,0,0
+34c0760406297a3c8fd5077fb7cd95b0,210.3585,365.1889,59,11.681
+352c23fe8a3d0640ea531a6bf223732c,446.7979,368.0638,24,10.94
+35b9a3e9871499893f76c8e6c648562c,206.9406,237.3598,124,25.7955
+375a52b012066845a2eeb5032a92fc6b,140.8095,296.2358,122,23.696
+380eb569a5750648434cc8ae8da4a0a9,307.5681,295.2394,111,16.4682
+383c27906392e9ce57f6ab5ef1cb6f62,177.0798,257.9096,93,15.4716
+385f1f49b0c20563177c36b7470f1c46,189.1676,297.1729,91,28.1598
+398208da1bcb6a88e11a7314065f13ff,0,0,0,0
+39ebb8121ea6faec0405a4e8db883b55,370.9993,237.3598,86,52.826
+3a5bbc2f1f5d6d76a48ba5300105d998,117.3919,243.8538,63,7.394
+3f6431400c2a07a46386dba3929da45d,0,0,0,0
+4001d754871a8da824b8444e32dc6e0f,224.3718,301.9579,89,52.9938
+40c95c9be0bd7c290534ce374c58bec9,353.7289,301.4023,110,20.8979
+437e42695e7ad0a1cb834e1b3e780516,149.8618,345.3652,121,43.0654
+43f2ef8f53e1aa03bfb6378d0c20a8ac,305.3758,324.516,436,15.0542
+44988c6efa451e8d496188cb30669d44,393.5574,258.8925,56,49.4686
+4521c94debf37a4dc9f3b70366a21640,325.8832,262.994,174,25.0697
+4521c94debf37a4dc9f3b70366a21640,161.1409,230.1822,73,25.985
+48e592418247393234dd658f9112c543,314.8447,321.4369,157,11.4518
+4a782bbc2608288a3ed05e511af6f8bb,0,0,0,0
+4af17bcb31669a9eab0b6ef8e22a8dcf,440.3825,265.3865,68,27.5559
+4baa552f3a11782f39e16b345d401fb8,0,0,0,0
+4cc8af2efef2f41bf70684be25276ce5,0,0,0,0
+4cd70a98baca46b116071b32788d3c2d,172.2075,349.6038,196,8.2147
+4cd70a98baca46b116071b32788d3c2d,192.5854,373.7336,177,27.5898
+4d7df08f074b221eec6311c2617a5ba8,349.8084,408.2543,81,26.0119
+4dbda61d574417c7f25d6e9a8f0749a7,223.0047,270.5134,108,15.8555
+4dbda61d574417c7f25d6e9a8f0749a7,325.1996,259.9179,100,24.1875
+4dcd34bd9b10f96453b63d4f55d1fd44,367.5814,375.7844,71,15.0542
+504e447ad62ea9ebb283873e044b5dd2,394.9246,244.8792,102,50.1394
+51bd5c556c77ecdaf489d8dd9f7a05f1,188.1422,358.0113,64,56.3112
+51fbac477a3639f983904fc4d42b8c15,197.7123,408.2543,99,15.7816
+51fbac477a3639f983904fc4d42b8c15,187.4586,403.4693,198,10.612
+5267ea7baf6332f29163064aecf6e443,376.468,268.8044,102,54.959
+54056288ab97cebc4b0ea33c23f47ff6,188.8258,378.5187,71,7.0379
+54056288ab97cebc4b0ea33c23f47ff6,91.7577,370.9993,57,6.1901
+5572cc61f851b0d10d6fec913ae722b9,386.0381,344.6816,90,20.5073
+5572cc61f851b0d10d6fec913ae722b9,144.0514,292.7296,133,42.7988
+55c01868f1d9c37fa3f174dc3c0d44e8,128.181,281.2095,130,11.5624
+55c01868f1d9c37fa3f174dc3c0d44e8,125.9366,241.1195,58,5.206
+56462ba8833fc842d16be7e311214404,323.3842,361.4237,100,26.0017
+56462ba8833fc842d16be7e311214404,36.0461,236.6762,33,8.2029
+570ea80b0dcc08f3e8751a6f4b2b1cd5,93.4666,324.516,28,17.891
+573a661e2d784f9385a3b78c9757ddad,331.01,228.8151,262,35.1362
+57822feb6186b788c4e1877123428454,404.0929,291.6831,124,15.2644
+57822feb6186b788c4e1877123428454,176.8632,348.783,80,26.1195
+5782e6873c666529c6a66421acb043dc,332.3772,284.8685,129,67.7605
+592c2481f17d6a2cecfe7bbb6a27722c,348.8723,338.5957,140,7.7358
+592c2481f17d6a2cecfe7bbb6a27722c,188.8258,357.3278,139,10.634
+592c2481f17d6a2cecfe7bbb6a27722c,417.1409,285.2103,114,10.612
+59fc9d939f05bf3023c1387c1c086520,142.0007,158.0648,44,13.6716
+59fc9d939f05bf3023c1387c1c086520,374.7368,253.4737,68,4.9185
+5ade88428e6463fa212d4c287228e8ed,201.8138,319.3892,201,9.2977
+5ade88428e6463fa212d4c287228e8ed,132.7724,238.0434,181,11.377
+5ade88428e6463fa212d4c287228e8ed,133.7977,383.6455,123,19.9061
+5b412509bc40a3aeb3b5efef1fdfcfc9,375.4426,278.7163,97,11.8004
+5b642ed9150bac6cbd58a46ed8349afc,0,0,0,0
+5c99ab7172afa78312fe73a3c0dd342f,339.2844,324.9883,407,5.1933
+5e0c8cba8eab51076ac0014049d770c1,327.6481,205.3,91,85.2622
+5fd33ea74e1ad740a201ae9b3c383fc5,192.6662,244.5312,116,28.9686
+608202eb3c368512e55e9e339a203790,179.0351,293.7364,159,36.8844
+608a7028689c6ab3aea5f116007169b2,378.5156,261.1545,91,9.974
+60b389fb2f7eeb912586d1a3ccc9dbbc,0,0,0,0
+61630ec628631f7fe3980f869e1a4fbe,135.6293,333.3923,76,33.5112
+61630ec628631f7fe3980f869e1a4fbe,88.6949,288.8305,65,12.2573
+6171d57221e26d1f15d3c71fe966ab18,179.8421,185.7895,159,6.9558
+624a34fa8fd36847724e749877343847,122.8481,302.3805,91,17.9656
+627499714e279203bd1294290f8fc542,74.3078,354.2455,76,8.0344
+627836151c555187503dfe472fb15001,79.5758,257.6364,94,6.482
+627836151c555187503dfe472fb15001,427.8804,282.3152,87,10.823
+627836151c555187503dfe472fb15001,436.75,295.5,80,4.5135
+627836151c555187503dfe472fb15001,301.7156,146.1208,81,7.3444
+627836151c555187503dfe472fb15001,101.12,168.38,74,7.9788
+627836151c555187503dfe472fb15001,361.3333,336.125,62,5.5279
+627836151c555187503dfe472fb15001,117.5918,190.2245,53,7.8987
+627836151c555187503dfe472fb15001,175.8824,349.5588,61,6.5795
+63b5be42543c98ac5392f1bfbda085bf,0,0,0,0
+648c99653d512edc1d28dd8e7054ceab,361.2273,240.5416,291,27.1649
+64a5a866461a3b6006efb0075e04dffe,0,0,0,0
+65073aadb60e398d8db1806f5ea2a082,169.061,337.2896,119,22.9571
+65073aadb60e398d8db1806f5ea2a082,82.6195,152.4377,43,14.1367
+6541df84fd779ba6513a530c128f4e9b,0,0,0,0
+65a380c07d416f78e85545eaaa2916a1,317.3416,307.3675,216,16.1786
+65a380c07d416f78e85545eaaa2916a1,301.7156,294.4013,204,27.7844
+65a380c07d416f78e85545eaaa2916a1,401.1234,304.3753,173,19.6466
+662153a685fb4268361bfbaca5e9ca23,336.2922,342.9416,87,12.6513
+668bb968918c63fad7d65581825b1048,188.8718,358.9487,162,7.0467
+668bb968918c63fad7d65581825b1048,143.3913,386.4783,129,5.4115
+668bb968918c63fad7d65581825b1048,368.7957,259.6882,50,10.8817
+66a92d789e440d3dbef3c69d20e20694,340.3,304.3,109,6.1804
+66a92d789e440d3dbef3c69d20e20694,164.9316,331.8061,102,18.2992
+66a92d789e440d3dbef3c69d20e20694,325.7255,333.6667,50,13.9573
+676467220abd8e2104417c5213664ef9,105.7812,195.4888,52,24.9522
+678c5ec1360784e0fe797208069e0bbb,204.7563,362.1572,112,28.4566
+6799964c08ad5ce7740defcd3bd037a6,0,0,0,0
+6857c76be618bb0ddced5f4fecc1695f,77,180.5,126,5.2926
+6857c76be618bb0ddced5f4fecc1695f,144.7188,277.4238,125,35.9845
+6969c031ee0c34053faff3aac9dd2da7,0,0,0,0
+6be677ba1631174397b0c1e26a46af30,359.5649,269.7987,88,31.259
+6cb2908fd789700db727dd96526bc342,169.2915,261.1001,173,47.0549
+6cb2908fd789700db727dd96526bc342,131.8247,379.8455,155,17.7427
+6ee742b62985570a1f3a142eb7e49188,219.9286,294.4013,173,33.9703
+6f43af3f636f37b9695b58378f9265cc,120.5208,252.8429,96,60.4908
+6f43af3f636f37b9695b58378f9265cc,368.5429,326.1143,83,9.4407
+6fd3af9174242c1b393fe4ba515e7a26,0,0,0,0
+713d8136c360ad0f37d6e53b61a7891b,163.7416,331.6377,129,41.2313
+71665cc6a7ee85268ca1da69c94bbaeb,137.9604,324.533,163,17.0007
+721949894f5309ed4975a67419230a3c,0,0,0,0
+72fd04cf3099b148d9ad361efb988866,328.7647,324.5662,177,18.6097
+733205c5d0bbf19f5c761e0c023bf9a0,196.9883,367.2117,74,18.6182
+7395f64fba89c2463a1b13c400adf876,173.3831,311.3571,238,9.5204
+74b1b748971c474a8023f6406c54b18a,386.1623,278.7753,137,27.3918
+75aef267ad112a21c870b7e2893aaf8a,317.0091,394.1416,101,20.8794
+761aeadb65fb84c8d04978a75b2f684c,0,0,0,0
+763ce10dfdd4662f15de3f5931d5534b,152.4377,409.1026,64,17.7427
+77033e4c1591403d1b1255607a20a983,154.7532,266.6883,58,17.1499
+775c5f8043e72b2284b5885254566271,185.6844,340.2818,144,11.9873
+77d6f5203d46073369d7038b2d58e320,0,0,0,0
+7842c108866fccf9b1b56dca68fc355e,0,0,0,0
+78c0a0104c0428e260cbd9e50eb7eea6,90.4154,187.5445,66,27.0105
+7917af5df3fe5577f912c5168c6307e3,306.7026,290.7442,297,30.7024
+799c0026d66479f7447ed0df5955f051,137.4766,258.8273,164,92.426
+79e0e507b1cd1d0c8107de4fd6b9e444,387.4922,197.6532,96,38.9597
+7bfba4540956c0b2c5b78b3623a4855d,337.6221,196.3234,301,58.5181
+7c2b72f9e0f5649c22902292febdc89f,0,0,0,0
+7d46ce019d79d13ee9ce8f18e010e71a,335.9597,333.9649,100,48.8987
+7fb1c8ffd78ca4b6869044251add36b4,390.5792,294.2386,121,26.4388
+80600d4a5fee7424d689ba7d0906d50f,404.1156,236.8844,134,39.5678
+817a99e1a60bcf4e37c904d73845ca50,0,0,0,0
+820dd342da11af3a062d1647b3736fdd,0,0,0,0
+823b5f08ce145f837066d2e19dab10c1,86.9416,375.5234,81,47.9215
+823b5f08ce145f837066d2e19dab10c1,106.2069,418.0345,61,6.0765
+8298238a27be6111214a9bc711608181,327.6691,375.4748,131,13.3034
+8326bb56a429c54a744484423a9bd9b5,192.6662,314.3494,215,20.1026
+8369f716ca2d51c934e7f6d44cb156e9,165.4039,329.9753,109,47.8799
+839502f9ff68fd778b435255690f3061,121.8506,352.5831,111,20.3431
+839502f9ff68fd778b435255690f3061,155.0974,373.861,77,14.8684
+84876a50f52476bcc2a63678257ae8b4,98.9104,254.8377,101,37.7376
+84a6c418d57bfc5214639012998356d4,203.9701,362.2247,114,11.3234
+85d59b470b927e825937ea3483571c6d,162.0792,289.7468,140,22.0333
+8601f5424bcf4cd8e7bc3d649e9995a2,360.2299,344.2714,68,41.8962
+868b024d9fa388b7ddab12ec1c06af38,0,0,0,0
+87cdb87db24528fdb8479220a1854b83,110.5468,417.0818,89,48.3532
+87cdf4626079509e5d6d3c3b6c8bfc2e,200.9779,400.4584,83,30.8461
+880980cc7e88c83b0fea84f078b849e3,414.0896,254.5052,103,20.7093
+880980cc7e88c83b0fea84f078b849e3,153.1026,199.3156,57,9.974
+8815efa67adb15b2f8cfd49ec992f48e,171.0558,302.3805,472,22.0233
+882107a204c302e27628f85522baea49,0,0,0,0
+88523579f4e325351665753e903cfdf5,386.0923,258.7231,43,9.0973
+88523579f4e325351665753e903cfdf5,359.4583,297.9583,60,7.8176
+88ae66cd575c45ec5bb0f1578e2f1c49,145.7883,400.126,83,41.4879
+8918c484841c5d0a532fe146e9da61bd,392.1468,318.0065,144,31.9515
+893fbc465b9d8a25569659a2bac154ef,337.6221,367.5442,114,64.9121
+898bd4c517fb9cf94c7d06dae56b0136,226.9104,240.2091,211,17.0306
+898bd4c517fb9cf94c7d06dae56b0136,216.6039,300.3857,217,14.354
+898bd4c517fb9cf94c7d06dae56b0136,143.1286,325.6532,188,15.9723
+89bfbba58ee5cd0e346cdd6ffd3fa3a3,121.5182,297.3935,204,26.5725
+8a97ff581c17a49a3ef97144efde8a19,0,0,0,0
+8b6e16b4e1d1400452956578f8eb97c4,397.7987,397.1338,111,26.3972
+8c63c8ebd684911de92509a8a703d567,0,0,0,0
+8e92c4db434da3b8d4e3cafce3f072fb,0,0,0,0
+8ed68f2dbf103a4bc0fd8708d8c1ac93,0,0,0,0
+8ee6f423ff988d10f2bb383df98c1b2e,389.8195,301.7156,186,35.9864
+90409f7fcfec3581033559f8340e48a9,190.3736,260.5824,137,10.7641
+90e3b396e1c1343a514eb5890833d3d8,360.8667,295.9308,139,22.2837
+90e5f4780b2f05136ff5f776a5cbc2af,136.7009,236.4626,87,16.5068
+91d29bc19205f8eb9a63de5b774a5575,403.9722,251.7222,158,9.5746
+91d29bc19205f8eb9a63de5b774a5575,167.301,298.2136,200,11.4518
+91d29bc19205f8eb9a63de5b774a5575,135.8143,373.861,112,40.9678
+91d29bc19205f8eb9a63de5b774a5575,389.487,347.5961,111,34.7933
+92abfd85dd6afb639e9a8b60aaa08262,174.0481,346.9312,93,55.989
+92abfd85dd6afb639e9a8b60aaa08262,162.4117,222.5883,82,31.3649
+9397a41c9e819a92eb5c86e0e652d7c1,0,0,0,0
+93a6f37a72f60498986374f57bfc30c4,168.3961,344.9364,363,15.8053
+95a27273c11db8bfb9fc27b1e64de6bd,0,0,0,0
+9660e4a23b8dd7d5056a622ee3568a41,98.0726,154.6872,92,15.0967
+9660e4a23b8dd7d5056a622ee3568a41,179.0351,299.7208,56,42.9746
+96acca47671874c41de6023942e10c16,212.9468,363.887,148,20.2996
+9703fd051751879432975535663150da,210.6195,288.4169,129,48.5812
+9a3174ffe867f602ee82c512a01420ee,123.513,260.4896,198,72.7732
+9b7524785a9bf40f0651deeb3b05b75f,0,0,0,0
+9c779a4e5e56c77131f8e99d5eacb766,161.7468,254.1727,42,100.5438
+9de4a1ebcdf1cfd8566ed1d9b63cbeb7,0,0,0,0
+9e5c2e760b94b8919691d344cfdbac7f,383.3118,253.7957,137,10.8817
+9e5c2e760b94b8919691d344cfdbac7f,155,304,134,5.1709
+9e922147900b3984c9345bdda573e882,411.0974,243.5338,94,44.7042
+9e922147900b3984c9345bdda573e882,353.3008,410.7594,71,13.0131
+9e922147900b3984c9345bdda573e882,365.5494,95.5857,71,20.8794
\ No newline at end of file
diff --git a/training/detector/labels/label_job3.csv b/training/detector/labels/label_job3.csv
new file mode 100644
index 0000000..0df4d1d
--- /dev/null
+++ b/training/detector/labels/label_job3.csv
@@ -0,0 +1,272 @@
+id,coordx1,coordx1,coordx1,diameter
+d7aa27d839b1ecb03dbf011af4bcb092,355.1529,202.7786,106,26.916
+e709901da9ba15a95d4a29906edc01dd,381.4524,227.5476,78,16.0181
+a88c585e7d81744eec091a6f0600bd7b,129.8582,244.4032,86,39.9739
+e58b78dc31d80a50285816f4ecd661e3,147.1306,379.0092,66,33.3397
+e5cf847e616cc2fe94816ffa547d2614,83.9286,285.0714,88,24.4285
+e6b3e750c6c7a70ca512d77defcfe615,0,0,0,0
+ed0f3c1619b2becec76ba5df66e1ea56,118.0909,191.7478,101,31.5341
+ed0f3c1619b2becec76ba5df66e1ea56,115.6549,203.623,97,39.4126
+721949894f5309ed4975a67419230a3c,0,0,0,0
+e54b574a7e7c650edc224cbdede9e675,170.1418,263.0142,251,13.3988
+e54b574a7e7c650edc224cbdede9e675,310.2143,355.1667,179,40.2586
+d2eecd9f13a6d474338045d0c91cffbd,142.2143,367.7381,226,20.1293
+d2eecd9f13a6d474338045d0c91cffbd,133.8333,329.6429,85,63.9001
+dbfbc12c7a943a2dc0e34bfd4a636bca,0,0,0,0
+d6d5ed3055d084a6abf0f97af3fe2ff0,314.7857,359.3571,68,39.3323
+763ce10dfdd4662f15de3f5931d5534b,153.2619,407.7381,64,20.0426
+d991b1760fb8705de655a1da068f7a6a,118.2143,365.4524,58,27.6079
+dc9854bcdcc71b690d9806438009001d,333.4256,177.8146,127,23.5883
+c610439ebef643c7fd4b30de8088bb55,164.9796,396.6422,43,30.5914
+c3e8db4f544e2d4ecb01c59551eb8ef0,425.6429,238.2143,116,17.5404
+c3e8db4f544e2d4ecb01c59551eb8ef0,420.6905,218.7857,114,36.6349
+a14e41eea93d7667a87d458d5cb28272,332.1576,234.7416,161,34.8156
+e572e978c2b50aca781e6302937e5b13,167.5603,230.6983,176,12.153
+6ee742b62985570a1f3a142eb7e49188,218.4048,290.4048,176,41.3188
+afb37b10bd304fa2c7b70cfaf1f489ed,0,0,0,0
+7842c108866fccf9b1b56dca68fc355e,123.5476,274.0238,107,21.3469
+e38789c5eabb3005bfb82a5298055ba0,86.4245,323.0288,24,13.3034
+e38789c5eabb3005bfb82a5298055ba0,303.7381,373.0714,71,10.8287
+e38789c5eabb3005bfb82a5298055ba0,347.1875,291.875,72,7.8176
+7c2b72f9e0f5649c22902292febdc89f,0,0,0,0
+ac68eb0a3db3de247c26909db4c10569,318.9762,326.5952,96,34.8982
+da821546432756d377777d7f4c41ca2f,417.9685,190.1989,99,42.1899
+da821546432756d377777d7f4c41ca2f,135.7381,406.9762,57,69.3961
+88ae66cd575c45ec5bb0f1578e2f1c49,146.4048,398.2143,83,42.7278
+d917c781760710015473eee9ce82e051,145.6429,234.0238,106,48.1871
+af4dfdda000c16c4cb77ea236cf1e524,143.8021,241.643,52,41.6737
+b8dc33b670bb078d10954345c3ffbb3a,216.881,332.6905,48,14.0074
+6fd3af9174242c1b393fe4ba515e7a26,0,0,0,0
+823b5f08ce145f837066d2e19dab10c1,86.5952,377.6429,80,54.4855
+cb64ff663195832e0b66a9bb17891954,157.4238,187.3642,86,19.6091
+c5887c21bafb90eb8534e1a632ff2754,116.339,324.2288,184,12.2573
+c5887c21bafb90eb8534e1a632ff2754,94.4924,278.2045,180,12.9641
+c5887c21bafb90eb8534e1a632ff2754,85.0714,291.1667,175,14.4762
+c5887c21bafb90eb8534e1a632ff2754,106.2188,312.8281,178,9.027
+c5887c21bafb90eb8534e1a632ff2754,176.2917,345.9667,128,12.3608
+c5887c21bafb90eb8534e1a632ff2754,395.4304,322.9873,73,10.0293
+87cdb87db24528fdb8479220a1854b83,106.4048,416.5,90,51.6412
+bc38f78d1194f57452f6bb5eed453137,396.6905,332.6905,41,106.2577
+be2be08151ef4d3aebd3ea4fcd5d364b,0,0,0,0
+a532c6f9405e6f3a4229ea6e04b0d975,178.0638,263.1619,112,32.8201
+c4c801ae039ba335fa32df7d84e4decb,0,0,0,0
+eb008af181f3791fdce2376cf4773733,102.5952,393.2619,65,162.1855
+6f43af3f636f37b9695b58378f9265cc,120.9227,251.9693,96,44.6388
+6f43af3f636f37b9695b58378f9265cc,143.3113,239.2878,104,29.4462
+e43afa905c8e279f818b2d5104f6762b,0,0,0,0
+c05acf3bd59f5570783138c01b737c3d,0,0,0,0
+77d6f5203d46073369d7038b2d58e320,133.0714,269.0714,97,15.633
+fd0c2dfe0b0c58330675c3191cef0d5b,79.3571,291.1667,109,23.3098
+fb57fc6377fd37bb5d42756c2736586c,143.3287,245.2736,51,23.5342
+ac00af80df36484660203d5816d697aa,160.6106,310.2601,106,28.5906
+839502f9ff68fd778b435255690f3061,123.566,353.8368,111,19.1492
+839502f9ff68fd778b435255690f3061,158.5952,377.2619,78,18.3491
+89bfbba58ee5cd0e346cdd6ffd3fa3a3,122.2965,296.4767,204,25.6318
+e8eb842ee04bbad407f85fe671f24d4f,183.1824,176.2948,88,28.9446
+7917af5df3fe5577f912c5168c6307e3,306.4048,291.5476,305,40.1503
+b6578699374a9954b9a8a9e7da2603b1,141.8333,256.119,119,30.0542
+b022a1d30d62ef2c1f0902f1a047a845,372.6905,363.1667,76,37.2087
+b84c43bed6c51182d7536619b747343a,68.0249,226.3607,119,22.6239
+a76b682e74918492c1f2ca4c13c29885,0,0,0,0
+fa45178d023325b255a3d4fc3e96cb7d,83.6591,273.8409,51,7.4848
+fa45178d023325b255a3d4fc3e96cb7d,191.3548,332.1613,109,8.8849
+c3b05094939cc128a4593736f05eadec,149.4524,352.881,136,29.1123
+8c63c8ebd684911de92509a8a703d567,89.6429,261.4524,98,26.5794
+a162d204827e4e89a2e5ba81cc53247a,166.3585,338.0283,120,11.6174
+c67e799bcc1e2635eb9164f6e8cf75f3,70.1765,306.7059,119,9.3049
+c67e799bcc1e2635eb9164f6e8cf75f3,187.5476,374.2143,390,27.2587
+c67e799bcc1e2635eb9164f6e8cf75f3,109.4524,293.0714,430,40.0417
+85d59b470b927e825937ea3483571c6d,162.7857,294.2143,142,19.1085
+b5de57869d863bdc1b84b0194e79a9d3,395.1667,316.3095,154,47.5382
+d92998a73d4654a442e6d6ba15bbb827,0,0,0,0
+f5717f7cbc08d8bd942cd4c1128e3339,141.3593,338.9891,75,47.136
+9e5c2e760b94b8919691d344cfdbac7f,381.8333,250.4048,136,18.9253
+9e5c2e760b94b8919691d344cfdbac7f,174.2143,326.2143,142,18.9253
+8b6e16b4e1d1400452956578f8eb97c4,393.6429,400.5,110,31.8363
+761aeadb65fb84c8d04978a75b2f684c,0,0,0,0
+75aef267ad112a21c870b7e2893aaf8a,321.6429,394.4048,102,26.797
+817a99e1a60bcf4e37c904d73845ca50,0,0,0,0
+775c5f8043e72b2284b5885254566271,184.119,338.7857,144,16.0181
+aea6f1621333074412b9a6acdcda31a9,342.5952,267.1667,108,33.8169
+95a27273c11db8bfb9fc27b1e64de6bd,0,0,0,0
+e659f6517c4df17e86d4d87181396ea6,212.6905,324.3095,116,25.235
+eed4db0cb0576c274de569e98a56a270,0,0,0,0
+df015da931ad5312ee7b24b201b67478,165.0714,385.2619,114,24.3094
+90409f7fcfec3581033559f8340e48a9,189.6364,260.0795,138,10.5851
+c67de8fbbe1e58b464334f93a1dd0447,0,0,0,0
+f25c425c827b35fcbaa23f2ed671540b,396.3095,208.119,81,18.5379
+f25c425c827b35fcbaa23f2ed671540b,382.2143,209.2619,78,20.5855
+ebd601d40a18634b100c92e7db39f585,342.9762,173.4524,134,31.0143
+aa2747369e1a0c724bea611ea7e5ffcf,0,0,0,0
+d09e4124b97b22ef45692b62b4ca7f03,367.3313,190.7398,53,25.0287
+d09e4124b97b22ef45692b62b4ca7f03,91.3793,278.3908,77,14.8843
+f3f6f40ccb01276d722d52701cab1754,222.9762,355.1667,298,41.2063
+91d29bc19205f8eb9a63de5b774a5575,136.119,371.9286,114,46.3261
+91d29bc19205f8eb9a63de5b774a5575,391.3571,349.4524,110,29.4099
+91d29bc19205f8eb9a63de5b774a5575,167.1765,297.8824,200,10.4031
+ea7373271a2441b5864df2053c0f5c3e,191.7381,232.5,97,77.4487
+9e922147900b3984c9345bdda573e882,352.5069,411.4167,71,13.5406
+9e922147900b3984c9345bdda573e882,151.7619,218.9524,85,8.9562
+9e922147900b3984c9345bdda573e882,410.7857,245.4524,94,46.6445
+9e922147900b3984c9345bdda573e882,381.662,372.0986,97,9.5079
+f8f66fca04d2e67eacd86ea154827a4c,382.9762,344.119,69,41.2415
+a19a122fe9a790576b57c6bd5cf9ff5c,335.2476,380.9825,95,30.7574
+e10c2b829c39d4a500c09caf04d461a1,328.119,242.7857,80,45.0105
+f3eafe72b1e9528116f3c430ab73a2ae,163.7713,362.5964,127,16.8503
+f3eafe72b1e9528116f3c430ab73a2ae,300.995,307.299,174,22.5111
+fb99a80cbb2f441bb90135bab5b029fe,0,0,0,0
+fc545aa2f58509dc6d81ef02130b6906,109.5,175,131,8.1369
+fc545aa2f58509dc6d81ef02130b6906,143.2018,235.4495,177,11.7806
+8298238a27be6111214a9bc711608181,327.7153,375.562,131,13.2073
+eaf753dc137e12fd06e96d27f3111043,106.6278,273.9917,92,21.4095
+eaf753dc137e12fd06e96d27f3111043,158.2143,286.2143,57,66.3251
+cf0a772e90a14d77d664ce9baedf0e5c,0,0,0,0
+ac3345a5a05655c6bcce7d0b226a0042,133.096,316.6215,115,15.0121
+a32e7fdbc0db97e35aabd7c931a582ea,0,0,0,0
+9b7524785a9bf40f0651deeb3b05b75f,0,0,0,0
+e56b9f25a47a42f4ae4085005c46109c,68.5556,223.5556,57,7.5694
+8ee6f423ff988d10f2bb383df98c1b2e,395.9286,305.6429,182,39.5971
+92abfd85dd6afb639e9a8b60aaa08262,162.1254,223.4775,82,30.0666
+92abfd85dd6afb639e9a8b60aaa08262,172.6905,346.0238,93,62.4808
+e2b7fe7fbb002029640c0e65e3051888,0,0,0,0
+cfbcb16fea277226d6771d8b1966397a,339.5476,328.881,180,49.3418
+868b024d9fa388b7ddab12ec1c06af38,366.2143,287.7381,57,105.8856
+f2f23b265b2a3b977cb81fe3193d7c2c,0,0,0,0
+80600d4a5fee7424d689ba7d0906d50f,403.5476,242.7857,126,60.8094
+733205c5d0bbf19f5c761e0c023bf9a0,197.0714,364.3095,74,22.8698
+74b1b748971c474a8023f6406c54b18a,350.9762,235.1667,146,20.4724
+74b1b748971c474a8023f6406c54b18a,388.5527,279.453,137,21.1402
+fd2dd970bd3d91e5b26d7e57c03f70af,135.2337,273.5647,196,33.3397
+bbe21f027a1df4b07016b474b48d3f65,351.08,165.7267,56,13.8198
+f6c9e875d7adfe7add08f43528810f72,362.2988,240.9084,184,17.8769
+f6c9e875d7adfe7add08f43528810f72,85.4524,345.6429,109,40.8384
+7d46ce019d79d13ee9ce8f18e010e71a,336.119,337.2619,101,55.368
+7d46ce019d79d13ee9ce8f18e010e71a,171.1765,138.298,58,18.0188
+f467795ce3b50a771085d79ae8d29ecc,320.119,295.7381,146,32.1448
+6cb2908fd789700db727dd96526bc342,132.3095,379.9286,155,23.6313
+6cb2908fd789700db727dd96526bc342,167.3571,254.5952,170,66.5654
+6cb2908fd789700db727dd96526bc342,110.2143,246.2143,172,61.4125
+ac9c16f3f287f0e0b321fb518ac71c75,343.3571,253.0714,90,39.3323
+893fbc465b9d8a25569659a2bac154ef,340.6905,371.9286,114,77.9529
+d7e5640b52c8e092ec277febc81478da,348.6905,382.2143,62,135.8201
+c1673993c070080c1d65aca6799c66f8,138.2917,216.9896,73,11.0558
+c1673993c070080c1d65aca6799c66f8,366.9762,216.5,92,15.1808
+880980cc7e88c83b0fea84f078b849e3,415.6028,255.8154,102,23.3441
+880980cc7e88c83b0fea84f078b849e3,155.6063,202.3858,58,12.7162
+e537c91cdfa97d20a39df7ef04a52570,140.6578,283.8128,103,15.4304
+d2b47d9034d38a410f00dabba9754d91,210.7857,347.5476,66,36.2926
+d2b47d9034d38a410f00dabba9754d91,389.0714,283.5476,34,21.0732
+cb94c3f894fc93c1ec0eb436c8564ed3,218.8288,334.9009,50,11.8882
+9660e4a23b8dd7d5056a622ee3568a41,98.069,154.7586,92,14.8843
+9660e4a23b8dd7d5056a622ee3568a41,185.6429,302.2143,56,36.7772
+aa55708fcc8bf27b605bcd2fca0dc991,391.7381,349.8333,105,27.4709
+b158f44c31f4121c865c828ff79fc73d,240.7418,253.9296,97,16.4682
+87cdf4626079509e5d6d3c3b6c8bfc2e,201.2619,403.1667,82,32.1448
+a853993fd839a0ee61f2ca73c4e497a6,0,0,0,0
+7bfba4540956c0b2c5b78b3623a4855d,339.9286,199.7381,299,67.6338
+f1a64fda219db48bcfb8ad3823ef9fc1,0,0,0,0
+898bd4c517fb9cf94c7d06dae56b0136,143.4959,327.7397,186,17.5535
+898bd4c517fb9cf94c7d06dae56b0136,227.8844,242.6131,211,15.9177
+898bd4c517fb9cf94c7d06dae56b0136,217.3618,299.6784,216,15.9177
+90e5f4780b2f05136ff5f776a5cbc2af,136.5147,236.5343,87,16.1165
+8a97ff581c17a49a3ef97144efde8a19,0,0,0,0
+cd104ad99d5b939b6bdd28b154e28085,182.5952,141.4524,66,31.4695
+cd104ad99d5b939b6bdd28b154e28085,183.7381,261.0714,58,52.7698
+df761dd787bfc439890740ccce934f36,105.9234,272.5404,90,17.2977
+7fb1c8ffd78ca4b6869044251add36b4,390.3737,293.8701,120,26.75
+88523579f4e325351665753e903cfdf5,435.1667,333.8333,65,41.1711
+a13d6c5f8f86d74e16c10cf9294bca31,172.6905,362.7857,44,39.7726
+e9ccf1ce85c39779fafb9ec703c71555,375.0682,334.4318,195,7.4848
+e00832e96709eb85f8e0e608ca02c2b5,316.3095,373.0714,90,24.0574
+b7045ebff6dbb0023087e0399d00b873,204.8317,327.5721,148,16.2737
+f76143416ee2c8e1251f45f108fed468,342.2143,252.6905,115,51.927
+c0f0eb84e70b19544943bed0ea6bd374,118.8807,270.4187,63,24.2273
+c0f0eb84e70b19544943bed0ea6bd374,203.5476,220.6905,50,41.4311
+c0f0eb84e70b19544943bed0ea6bd374,175.7381,277.4524,73,49.4065
+f17867cc3e579dc2fc6f0334bc43a91d,174.939,127.4695,126,14.4503
+9e98136d07b953c3362e0a132c8810b6,97.4182,234.5545,104,11.8345
+ad7e6fe9d036ed070df718f95b212a10,436.3095,239.7381,115,31.6901
+9c779a4e5e56c77131f8e99d5eacb766,183.244,249.1651,45,93.0075
+bb4b43d0dc4d9d2b61150df6556f6490,0,0,0,0
+8918c484841c5d0a532fe146e9da61bd,390.5952,316.3095,143,33.6362
+c1ba619e3b49e0cb7798bd10465c2b29,0,0,0,0
+fbae4d04285789dfa32124c86586dd09,0,0,0,0
+b6d8dd834f2ff1ed7a5154e658460699,84.8312,370.487,59,14.0028
+93a6f37a72f60498986374f57bfc30c4,170.1506,345,364,14.5381
+90e3b396e1c1343a514eb5890833d3d8,361.2947,295.7816,138,21.9962
+9703fd051751879432975535663150da,206.5952,287.7381,130,54.8624
+cd10ceca9862ba0cc2ffd0ed8c9b055c,323.1522,331.6739,135,17.1127
+9a3174ffe867f602ee82c512a01420ee,124.6905,262.9762,200,83.2013
+f7a03adba817f2a2249b9dee0586f4be,0,0,0,0
+fda187bfb1d6a2ecd4abd862c7f7f94c,62.5952,221.4524,83,47.2442
+f2ca85bb9ae82a3d79b9f321f727ac19,407.5152,318.9333,159,14.4943
+b17cb533d71d63d548ce47b48b34c23c,194.7857,245.8333,115,48.3914
+9f52323d216f89d300612cfac0122d8b,0,0,0,0
+af6d573b8c6804e14e3a7b07a376e593,457.2619,218.7857,84,21.8176
+96acca47671874c41de6023942e10c16,215.3571,363.9286,150,27.0235
+e5c68cfa0f33540da3098800f0daae2c,0,0,0,0
+d81704ee56c124cc1434640918a3299c,374.5952,332.3095,146,51.9941
+adc3bbc63d40f8761c59be10f1e504c3,376.825,279.4812,317,14.273
+9397a41c9e819a92eb5c86e0e652d7c1,0,0,0,0
+ac366a2168a4d04509693b7e5bcf3cce,75.1196,254.6277,57,21.6461
+b6687898fe385b68d5ae341419ef3fdd,117.0469,273.7266,205,12.7662
+c2e546795f1ea2bd7f89ab3b4d13e761,345.5132,362.4079,102,13.9116
+c2e546795f1ea2bd7f89ab3b4d13e761,341.3403,270.7914,142,49.3529
+713d8136c360ad0f37d6e53b61a7891b,160.881,333.0714,129,52.1668
+bda661b08ad77afb79bd35664861cd62,126.9762,265.6429,90,73.2777
+f29d00ddf6d9846aa600c3f0edf5f952,355.1042,278.6718,55,18.1595
+f29d00ddf6d9846aa600c3f0edf5f952,182.2143,354.4048,208,29.9381
+f29d00ddf6d9846aa600c3f0edf5f952,118.5952,242.7857,66,29.4099
+f29d00ddf6d9846aa600c3f0edf5f952,146.4048,214.5952,71,24.7238
+f29d00ddf6d9846aa600c3f0edf5f952,98.4048,265.6429,59,19.7655
+a8e650f8494e894be06c9cee08702aa9,177.0857,289.5,98,13.3512
+8ed68f2dbf103a4bc0fd8708d8c1ac93,0,0,0,0
+a2d9e657a673798f9ebdfec1b361f93a,368.881,379.1667,44,40.2081
+ba71b330a16e8b4c852f9a8730ee33b9,137.0498,371.5,50,22.6239
+77033e4c1591403d1b1255607a20a983,154.7104,266.6335,58,16.7746
+882107a204c302e27628f85522baea49,0,0,0,0
+c2bdfb6ab5192656b397459648221918,189.8333,299.9286,21,10.2504
+799c0026d66479f7447ed0df5955f051,89.2826,228.4003,157,91.67
+799c0026d66479f7447ed0df5955f051,133.4524,261.8333,166,102.9136
+fe45462987bacc32dbc7126119999392,370.4048,331.5476,116,32.3249
+8369f716ca2d51c934e7f6d44cb156e9,166.9404,330.7414,111,45.0363
+ac57a379cfea05c07d9befe8b9359495,179.8714,388.7857,121,9.4407
+ac57a379cfea05c07d9befe8b9359495,350.9227,258.8069,223,17.224
+c020f5c28fc03aed3c125714f1c3cf2a,336.5,421.4524,200,61.0143
+c0625c79ef5b37e293b5753d20b00c89,357.8333,286.5952,55,37.1463
+7395f64fba89c2463a1b13c400adf876,0,0,0,0
+8326bb56a429c54a744484423a9bd9b5,194.6304,317.2355,215,18.746
+d777a77cc7a2ec2f1eed68799cc9075c,131.5476,298.0238,101,49.029
+d7713d80767cfdaad5e3db537849d8d0,0,0,0,0
+e3423505ef6b43f03c5d7bde52a5a78c,118.5488,281.2952,84,37.8974
+b635cda3e75b4b7238c18c6a5f1858f6,0,0,0,0
+71665cc6a7ee85268ca1da69c94bbaeb,137.6618,323.9608,163,16.1165
+d9a2bea7df4a888313374beb142cf9c0,149.9848,334.1364,29,9.167
+820dd342da11af3a062d1647b3736fdd,190.9762,309.0714,208,83.2187
+9de4a1ebcdf1cfd8566ed1d9b63cbeb7,0,0,0,0
+8601f5424bcf4cd8e7bc3d649e9995a2,352.5,351.7381,68,55.1632
+a4dc34f2731b62f60c6c390a39fe11b2,176.5,302.5952,81,67.3457
+d244870d213a21efa86e86c951d8c9a2,436.6905,355.9286,78,77.4149
+ac4c6d832509d4cee3c7ac93a9227075,130.7857,348.3095,119,28.6399
+f42a0343e5b5154c6a184fc955d8f20f,174.5952,352.5,143,47.367
+84876a50f52476bcc2a63678257ae8b4,99.1667,253.0714,101,40.5746
+f725f46908f16062fd12c141eb47c6a7,334.2062,384.3541,50,18.0893
+d8ed783494996f55a587270a212f7d5b,408.5221,286.9116,39,17.8055
+78c0a0104c0428e260cbd9e50eb7eea6,90.1511,187.518,66,26.6068
+a784a51caee14229d46777f2a9770a5f,93.8333,210.0238,88,16.0724
+a784a51caee14229d46777f2a9770a5f,166.5952,209.2619,119,59.8859
+79e0e507b1cd1d0c8107de4fd6b9e444,96.881,274.0238,46,179.0541
+79e0e507b1cd1d0c8107de4fd6b9e444,388.6905,198.5952,96,54.5441
+a70fd23bd8d535ffd42259cb91f4c5ca,98.7926,298.1646,76,33.606
+f63f2f63e2619012b4c798fd638c8b8a,0,0,0,0
+c8cfb917b0d619cb4e25f789db4641f8,340.6466,308.258,118,18.9823
+72fd04cf3099b148d9ad361efb988866,328.5531,324.2784,177,18.6439
+ed49b57854f5580658fb3510676e03dd,130.6316,256.4605,155,9.837
+b7ef0e864365220b8c8bfb153012d09a,396.3095,240.5,172,45.8727
+8815efa67adb15b2f8cfd49ec992f48e,170.7857,302.5952,472,21.6574
+84a6c418d57bfc5214639012998356d4,204.6905,362.0238,115,19.941
+8e92c4db434da3b8d4e3cafce3f072fb,190.5952,302.2143,99,43.6685
+b8bb02d229361a623a4dc57aa0e5c485_1,147.792,250.312,76,21.851
+b8bb02d229361a623a4dc57aa0e5c485_2,145.6203,253.3768,76,20.9587
+f938f9022abf7f1072fe9df79db7eccd,104.119,250.7857,78,57.3254
+b83ce5267f3fd41c7029b4e56724cd08,192.881,370.4048,51,70.4422
\ No newline at end of file
diff --git a/training/detector/labels/label_job4_1.csv b/training/detector/labels/label_job4_1.csv
new file mode 100644
index 0000000..b11f776
--- /dev/null
+++ b/training/detector/labels/label_job4_1.csv
@@ -0,0 +1,445 @@
+id,coordx1,coordx1,coordx1,diameter
+0030a160d58723ff36d73f41b170ec21,117.9563,156.4961,126,22.2551
+0030a160d58723ff36d73f41b170ec21,112.0429,116.919,113,10.344
+003f41c78e6acfa92430a057ac0b306e,0,0,0,-1
+0092c13f9e00a3717fdc940641f00015,201.5777,194.2784,96,25.9282
+00986bebc45e12038ef0ce3e9962b51a,0,0,0,-1
+00cba091fa4ad62cc3200a657aeb957e,115.2857,139.5495,70,10.7641
+00cba091fa4ad62cc3200a657aeb957e,111.1147,187.7248,68,16.6603
+00cba091fa4ad62cc3200a657aeb957e,68.1571,314.4048,31,14.8304
+0121c2845f2b7df060945b072b2515d7,0,0,0,-1
+013395589c01aa01f8df81d80fb0e2b8,0,0,0,-2
+01de8323fa065a8963533c4a86f2f6c1,0,0,0,-2
+01e349d34c06410e1da273add27be25c,0,0,0,-1
+01f1140c8e951e2a921b61c9a7e782c2,0,0,0,-1
+024efb7a1e67dc820eb61cbdaa090166,177.0556,302.5278,66,6.7703
+026be5d5e652b6a7488669d884ebe297,0,0,0,-1
+0334c8242ce7ee1a6c1263096e4cc535,416.3348,229.6802,65,24.4366
+03fb0d0fdb187ee1160f09386b28c3f2,0,0,0,-1
+03ff23e445787886f8b0cb192b3c154d,137.0333,344.881,91,24.6537
+043ed6cb6054cc13804a3dca342fa4d0,0,0,0,-1
+0482c444ac838adc5aa00d1064c976c1,0,0,0,-1
+04a3187ec2ed4198a25033071897bffc,0,0,0,-1
+04a52f49cdbfb8b99789b9e93f1ad319,184.5762,313.7952,108,15.8944
+04cfc5efa4c8c2a8944c8b9fa6cb04d1,0,0,0,-1
+04e5d435fa01b0958e3274be73312cac,0,0,0,-1
+04fca9fbec0b803326488ade96897f6e,0,0,0,-1
+05a20caf6ab6df4643644c953f06a5eb,129.719,343.6619,170,22.9038
+0679e5fd67b7441b8094494033f3881f,0,0,0,-1
+0700108170c91ea2219006e9484999ef,0,0,0,-1
+07abb7bec548d1c0ccef088ce934e517,124.2333,139.4714,150,9.8283
+07fdb853ff90ce3c6d5c91f619ed714e,0,0,0,-1
+080e6a00e69888fd620894f9fd0714b1,0,0,0,-1
+08528b8817429d12b7ce2bf444d264f9,0,0,0,-1
+0852f5124d69d7f8cd35fa31e1364d29,0,0,0,-1
+086f95a932c83faed289854083f48831,329.0333,322.3286,142,13.6294
+0890a698c0a6ce5db48b1467011bf8d2,0,0,0,-1
+08acb3440eb23385724d006403feb585,0,0,0,-1
+09b1c678fc1009d84a038cd879be4198,0,0,0,-1
+09ee522a3b7dbea48aa6d39afe240129,0,0,0,-1
+09fdf599084b816247ba38d95b3c9d80,0,0,0,-1
+0a099f2549429d29b32f349e95fb2244,0,0,0,-1
+0a0c32c9e08cc2ea76a71649de56be6d,0,0,0,-1
+0a38e7597ca26f9374f8ea2770ba870d,101.681,357.681,59,16.9794
+0bd0e3056cbf23a1cb7f0f0b18446068,0,0,0,-1
+0c59313f52304e25d5a7dcf9877633b1,0,0,0,-1
+0c98fcb55e3f36d0c2b6507f62f4c5f1,0,0,0,-1
+0ca943d821204ceb089510f836a367fd,85.8333,334.519,38,42.2642
+0d19f1c627df49eb223771c28548350e,0,0,0,-1
+0d2fcf787026fece4e57be167d079383,0,0,0,-1
+0ddeb08e9c97227853422bd71a2a695e,0,0,0,-1
+0de72529c30fe642bc60dcb75c87f6bd,0,0,0,-1
+0e7ffa620c6db473b70c8454f215306b,0,0,0,-1
+0eafe9b9182b80c6d67015a2062f5143,0,0,0,-1
+0eb39d23d0f68ade9b5d8e6b3aee04d2,0,0,0,-1
+0ee336c585bf7eb1011df476891c5102,0,0,0,-1
+0fb1b54da1e66c60a57db9c52f945e25,0,0,0,-2
+0fe244f21893c45fbb877f54d008518b,0,0,0,-1
+0fe9dd36f4dece7f4ec017433c4d4a50,0,0,0,-1
+101a2999d28ce05788e6add3a28d4726,0,0,0,-1
+1030bb45e9f660c3466f013dcb270520,0,0,0,-1
+1098cb63ea33f752a850929234576bcb,0,0,0,-1
+10a9c32039971eb12f3aecf76ac20f8c,0,0,0,-1
+10aa518193fa5b89b305a806d1dfb150,0,0,0,-1
+10f03fe0b77d39c758d6fb12304edfdb,375.9667,379.6238,55,12.068
+10ff16e329c64a6a290a7a4139a5f4ae,0,0,0,-1
+11616de262f844e6542d3c65d9238b6e,0,0,0,-1
+1183f213c1c821df18aad63890920403,0,0,0,-1
+11b09ff9de7382d83f79cc81f89f5894,0,0,0,-1
+11f10c2a0bfd231deeec98d69e4d0767,157.7571,221.7571,89,18.9247
+124c4188604434bcdec8358c8ddf9a8b,0,0,0,-1
+124e68a78f9c092a2f16f9214e91268f,107.0909,404.2424,83,9.167
+1278988821a696e534c6c93ecdd4ff0c,0,0,0,-1
+1344e604281e68ac71f25c02e7637992,322.9381,300.9952,220,15.6114
+135f21a84ac903a1d8dfbb0dfe46d792,0,0,0,-1
+14248ec22193bed1e087755df5a28509,0,0,0,-1
+149ff4b37a684a73869d2d88e3fd4d0e,0,0,0,-1
+14afefc82d992018c485949285d20c03,0,0,0,-1
+14c534e0b7c3176d9106c6215d0aa8c6,0,0,0,-1
+154a79706bcecd0402b913d4bee9eed7,0,0,0,-1
+155893351afed6c68893397d19555fd8,0,0,0,-1
+1615ace332b9d79be4e0e9fa32c71e9e,0,0,0,-1
+1631637f08f27347e8f23d7a0e18c100,0,0,0,-1
+16377fe7caf072d882f234dbbff9ef6c,0,0,0,-1
+166a2a476b7b84c975fb65162acc0798,0,0,0,-1
+16a4184e565f589622a70e82957ab54e,421.8281,262.9063,89,9.027
+16a4184e565f589622a70e82957ab54e,186.1667,356.4231,119,9.9656
+1748ad43b222be66f3e5ae4bd70c02ac,111.4333,335.1286,91,24.2894
+174a9fc87f54d6def3730954fbafc99d,0,0,0,-1
+178663e1e238cdfa4d4eb9679e5d0aa4,0,0,0,-1
+17f5ae9fa49c4e47624f344d29bd03eb,0,0,0,-1
+17ffaa3e8b53cc48e97fc6b87114e6dd,446.6,269.89,83,15.9577
+180737a8b34cf2c88b00dfad3e7556ae,0,0,0,-2
+186a0877503b047a77eb9b38083be9c1,0,0,0,-1
+186d95f7c17fd666726c10251072d44b,391.8143,355.2429,135,18.9639
+18f49fee33af677f0ce2ba655c5ec835,0,0,0,-1
+19409b302d6c143d4f754146e91d4cfe,0,0,0,-1
+195842462645f0f331147a4c6b129a37,0,0,0,-2
+199ff05d08ade6e298d37cc542bc3565,0,0,0,-1
+19bb6a9bc007ad75a4777e5298354cb4,0,0,0,-1
+19ca60da880961c50f1b99b66f252e8f,0,0,0,-1
+19d95b5828aeba8073fcbb12979f312b,0,0,0,-1
+19f3b4dea7af5d6e13acb472d6af23d8,0,0,0,-1
+1a41350d4bbd74b7e0e28239cefa84c2,0,0,0,-1
+1a91ca95390756518700877893ac195b,0,0,0,-1
+1a9e2aad4b87512636f4f9d82c36a3ef,0,0,0,-1
+1acbe17dc8f9f59d2fd167b2aa6c650f,0,0,0,-1
+1b17c83c3b0cb973e41f9121e562d030,0,0,0,-1
+1b2355e6054759f2f0eb2542ed382b78,0,0,0,-1
+1b7ca8dad5c36feb0a6abf8079173e22,106.0677,199.4135,175,13.0131
+1bb17a55702a78142cd05cd1063c82c8,0,0,0,-1
+1be4cf2de84adac4de0e090c9a15461c,171.7762,385.1095,42,17.7496
+1c05dea5723caf192af34ceb5804468f,0,0,0,-1
+1c42a5da837f4122d2c3b59ca9b5f0fb,0,0,0,-1
+1c498f306808952739e7a3a3a2439d1e,0,0,0,-1
+1c81d86923dad37b411f3a5936eb622d,0,0,0,-1
+1ddb5d17d9db61c8ea0fd58d00df05ef,0,0,0,-1
+1e33cb12436a64853c1ae9e918633e05,0,0,0,-1
+1edf5480bf676f8342a7d516bab58fa0,0,0,0,-2
+1ff6e2a80eb74396e09460c61ae69fb0,0,0,0,-1
+204bdd4a15f023eea66190972b66fd0f,0,0,0,-1
+20809d879e5a966cc537beb42735a67f,0,0,0,-1
+20c73e37fc89e007ae5b242480830860,0,0,0,-1
+2117642550461db380a019bbd10a95e5,0,0,0,-1
+2143d78ca33eb69f667edd80ddbff6de,0,0,0,-1
+21bdacdcdb87bf401f34d5d582247c77,0,0,0,-1
+21cfe28c4a891795399bb77d63e939d7,0,0,0,-1
+21d449f3ae00ea302e5aa15d7df65465,0,0,0,-1
+2276fd918ac100cec3ed8036f6ad401c,132.0354,167.2035,57,11.9948
+2346e52f9370d9dd58172eb44b2b5d87,383.2357,206.5892,65,19.4461
+234ac5dd589d09a4b2a753ff206d5588,0,0,0,-1
+23e309ef3a674bcd9c8df40614b93a8e,0,0,0,-1
+24031ba88c58797148475f6d4d5a085b,52.7538,299.1692,53,9.0973
+24626abe1c4544fb39d4e96e33275789,0,0,0,-1
+24deb9f7adc838e4a4aaa2c905c548e6,303.4333,327.2048,215,7.4152
+2505ca2e3cd132f69fde96ba4bb50f7b,0,0,0,-1
+25196c504274d166e81c745d32f30c72,0,0,0,-1
+25782c40c29f7d774f8b644f3e68b590,0,0,0,-1
+25a3b616f6cc89e74f6502d65b687972,363.0484,289.4032,59,8.8849
+25a3b616f6cc89e74f6502d65b687972,340.9344,306.6393,58,8.8129
+25c1c4f008e8addc4d386cab58815052,0,0,0,-1
+25c369973827571098bdebf2a15c6ef2,0,0,0,-1
+2615d445b6d3865407d1a4422d25058e,0,0,0,-1
+263fa87394ee296e31234364e75d05e2,0,0,0,-1
+264e5829ef58570c243bfd961098343f,0,0,0,-1
+26a2b8d6b94ee16ecf88fb28c57f377e,0,0,0,-1
+274297dd9a4f66148754944ae2b6731c,0,0,0,-1
+27e9f8b51aeee67918221f2df98e9cbc,0,0,0,-1
+28054f63c5a6ef24e06d8c34258babd6,360.2958,201.5493,119,13.4462
+28352e12fe29361dfd9613ed2e729192,0,0,0,-1
+28621a6988deb389673605447f46d3bb,0,0,0,-1
+28649e08938386e3b8eaa4a84baf5982,0,0,0,-1
+2885e3af725bc58dc1522d4bfb24bb2b,228.8,332,77,14.4943
+2922aac33a190fd3939de337fe3f0a34,0,0,0,-1
+2950df9632577cb4b3af2dbfe2086b11,365.8047,332.5742,48,18.0541
+29883252ce0ce3e052ce8cf4932623af,0,0,0,-1
+29a2105c99e7677c30c7fd0b2edb9fcd,0,0,0,-1
+2a48f50391e22040f28e258a74dcaf95,0,0,0,-1
+2a549c66f24af964de6f25165c55e331,0,0,0,-1
+2a6433cf347f7bd52ab796f083003832,0,0,0,-1
+2a65c8b6d5cc50866de8caa4caabbb6d,102.0556,273.3056,86,6.7703
+2b0ea2696c8a02af5ac22f142be28e17,0,0,0,-1
+2b2a95f76d7b6712690ee7be6838f868,0,0,0,-1
+2b89691a0744504491ef91d711d94918,0,0,0,-1
+2bb5f7e8f10e1e39b7f81b5aa98676ea,0,0,0,-1
+2bf773632e786951d6d594939e6f4713,0,0,0,-1
+2c51b9e7af4850d817f4aa0ddf90b852,0,0,0,-1
+2c8e0b1e8a3f10b1d59e4aa8fe68a32e,0,0,0,-1
+2ce2565b9839d8812cf0f9ad80371d3f,178.3547,178.5867,65,21.851
+2d8152c603e6c49593578bde8e388860,0,0,0,-1
+2d81a9e760a07b25903a8c4aeb444eca,150.8872,386.7216,38,16.5335
+2dabff545dbfcb9e0efd92220c6aebcc,0,0,0,-1
+2dbb8c6c6ea4ff5c62b34bdf9ea03158,437.3064,343.3144,30,11.7607
+2e26f46f1edc232be164c1fe2712e96a,0,0,0,-1
+2e59e2064d391f4b2587a08aff671399,0,0,0,-1
+2eb8aedb5274414e05041b7be65db3e3,0,0,0,-1
+2ed2ec628e6ad9d0aa8c2a9b7bf4c4ce,0,0,0,-1
+2f4e4a808cfb348d6ddc81de96f72077,0,0,0,-1
+2f7088e4008c0ef2c88b6764af8c8815,0,0,0,-1
+2fa939efbc3e1c2bc57ba5a98922ff3b,0,0,0,-1
+2fced53a125854edb9284ff12795caf8,0,0,0,-1
+2fd66be0a5e07b8bd4be1d8169cd846f,0,0,0,-1
+302336ac736ed66077456775a0a99adc,0,0,0,-1
+3043b5cc9733054f3ab5399c3c810406,0,0,0,-1
+310b403db75226a9a44d9a29c18917b7,55.1862,268.4626,77,15.7816
+313efe2e7ecf18a8d484f8b42f30da3e,151.5708,178.5721,62,30.9956
+3170d41d2bc132db30399fca6bc6f376,0,0,0,-1
+3187b6cf14ed2cbe611b01da5e161f21,0,0,0,-1
+31c090cf66ec7bf090801d14d63199b5,0,0,0,-1
+31d037f6e359b56aec064fd3e348adb5,0,0,0,-1
+31e82ed2c875eae8dfbfd70ac440458a,0,0,0,-1
+321364cc2393dccb7ba8894ee9d2b269,0,0,0,-1
+322d09835e9c6f621262ee68fd3ed596,0,0,0,-1
+323792e42c4f43448b2b1a9651ecb779,0,0,0,-2
+3244f802b7bd7c02ba7a8473802e947d,153,157,71,5.1709
+327c4e9f365aec05222e253d1a80a1d4,154.9887,219.245,65,28.7184
+328138837e6db638913332acb79c703e,0,0,0,-1
+3295f3f392d8e130155c8912b60161b5,0,0,0,-1
+331b14e413e88542855664c845c08c63,0,0,0,-1
+33293edbc834da033aa061f7d6a45fa1,0,0,0,-1
+335b129aacabdf9269b0bb12f148d15c,0,0,0,-1
+337e7a428e7342d1e7f53a04247f7ad8,0,0,0,-1
+338f9c6da34f61091a4c44b074b2f9e3,0,0,0,-1
+33da5fb759223c316e8cec9d884d1584,0,0,0,-1
+33e0e8629a377e4554b26e60a1007788,0,0,0,-1
+34007dd2549af2b82cc1206e550b5100,167.8333,206,109,10.7047
+3464083b3e6e7c11d1fba925f0b914cd,0,0,0,-1
+34b00e3b98072207edd20732558f7ab5,0,0,0,-1
+34cb3ac3d04e0d961e7578713bee6bb2,140.6335,356.3024,98,12.3044
+35105d801880bd889bac5ee3771ed38b,0,0,0,-1
+3557455d81f42ee54ad0544f36933e9a,0,0,0,-1
+356bc45910503ffde017a066581a3798,0,0,0,-1
+359951e3d2768249211361665b99b735,0,0,0,-1
+35ab1899e939be4e67923a1624c91365,57.9206,275.982,64,11.701
+366cfab448dbe55fd63b01adac0b1c56,0,0,0,-1
+36d0dff4c9eb340475888c2f93359e43,0,0,0,-1
+36dcb6b7463ada9ed78ce902d6f8ddc2,0,0,0,-1
+36f4fca6bbd993088ee024f93a61b722,0,0,0,-1
+37006435aca7184571bba3c907141e82,0,0,0,-1
+37030ab5889febdae6725740aa627f95,0,0,0,-1
+379d84cd171e6c0e58455c2fd0cf57ef,0,0,0,-1
+38d89e67d2ea7e2ab023c10f5f19f716,0,0,0,-1
+3938d2274f0576b70fffa9aa68af8874,138.241,163.5334,85,11.1278
+399a263bdfbf26c6969d8af98774be8c,423.6348,334.4279,65,19.4309
+39c3a2d2ca67bc7a1a22240ea571d50c,0,0,0,-1
+39c404ac6b5852fc8ff00d34bd35294f,235.9927,176.8632,83,18.3678
+39c404ac6b5852fc8ff00d34bd35294f,115.6829,375.4426,60,10.4344
+3a1a293ecad44010da9907bfc91d94cd,0,0,0,-1
+3a3a7a6b3d2a4ea6b1f5bc6ea715eab8,406.8872,337.8458,67,13.2727
+3a78dcf53effd732bc3880c029154272,0,0,0,-1
+3aedb9550977ed35e7d44555207ef739,109.5307,394.241,43,11.6409
+3b7384f374b73d2bd589ccbf1b651820,0,0,0,-1
+3b78adbbe463aba48bf29613ca37b2ea,0,0,0,-1
+3bbab45d770ecd681be143f67cb4e5f3,0,0,0,-1
+3bd4f83c5930e8c1e193ccc463543745,0,0,0,-1
+3c2dbbdeb857504a8b501fc013b99c90,0,0,0,-1
+3c5a0fc6890a1f84211cf8a75c1b83c4,359.7203,154.9887,78,10.2764
+3c73f5597780b7312b380373fb897f40,438.6736,164.9005,42,28.1515
+3c86ed658e82e542bc542886a59ea4f1,0,0,0,-1
+3cdd66bf14f0cff5cb46e95d5867de0d,166.5441,380.3824,64,9.3049
+3d2b2b0fa9697b298fbbc033481cdcc4,0,0,0,-1
+3d4e602819dca0f5eb48953841ff11d6,0,0,0,-1
+3d521ee3776eefb65953f89c0e1a4f96,319.0474,386.0381,81,11.2115
+3d5351d09a432a8de88e5b270d419ebf,0,0,0,-1
+3dfe8e80106f4136d2933ff72a16035c,0,0,0,-2
+3f057e68a02e9951b268227649f4a7d6,67.5217,313.9565,45,7.653
+3f28787cc3343445a8c5ecc4dae27a25,0,0,0,-1
+3f37745d6516c29c597b797c50fe7839,0,0,0,-1
+3fcfd27d83883f454ba2fe58dee4abea,57.5788,334.0861,33,18.6706
+402a18fa05523f80abb1e6d97793cc19,0,0,0,-1
+404e5dd2b032a223282f5a5e73c05418,0,0,0,-1
+4062f1ad138218af5a3dfa3186d2afe1,0,0,0,-1
+408646e125230c495be91fe171da736e,0,0,0,-1
+40c044145f5c87c12bd8c725924add3c,66.1235,200.1048,87,10.1621
+40c044145f5c87c12bd8c725924add3c,100.3889,382.7037,49,8.2919
+4131820511c86a5e6b1e7721ab687049,0,0,0,-1
+4165b6e956c0e46e94abf7d98f8d8fe2,0,0,0,-1
+4209cb1fbce28cd68da900eb9bef26b3,0,0,0,-1
+428e25dfddfe731fc73f4e1739422181,0,0,0,-1
+42bfcfb0e3965039947bd905b2fc3915,105.7586,329.4655,123,8.5935
+42bfcfb0e3965039947bd905b2fc3915,72.6175,283.1595,81,9.7873
+42bfcfb0e3965039947bd905b2fc3915,325.8832,359.3785,85,7.2665
+42bfcfb0e3965039947bd905b2fc3915,128.3291,76.3772,75,9.2977
+42dbd247a9e5f710926b7c049a00ff48,0,0,0,-1
+430596d1bfa6ec9a7bfa7359194a561c,124.9112,392.1903,104,10.9586
+432f8765e6b590ec00cc34c8d88456da,0,0,0,-1
+4348beb99dacd2cbf14983a2c64a00c6,307.0848,345.3652,60,16.9246
+435cd5883a2014f295a8081ea098674b,0,0,0,-1
+436fd6ccfc92afc44c7d3ccfe26b6129,129.3545,253.7657,63,26.1999
+43933b4021d93dd64854f318656c7d1e,0,0,0,-1
+43fecc8947e4fbb47968dc8ef7d8f4ec,163.1916,215.4853,67,8.7541
+43fefd3f810ef71e0073d2415e7a6713,0,0,0,-1
+440fb90654b1436e7c3bbdac991b8c1d,405.1782,200.4466,50,20.8687
+4419818b57ef8b0f8d6d95594adab922,63.9808,314.7404,40,11.5073
+448ce51772879fcd88f61c07b06347b2,0,0,0,-1
+44cd94d1228f4a70753b5dfc12703414,312.8952,358.0113,39,14.992
+456a7dd28233b398ac83f03c80447b5a,110.8979,348.0995,121,15.9583
+456a7dd28233b398ac83f03c80447b5a,122.1769,353.5681,114,25.2091
+45a8417be8f56b401bd7b5d106f5acdd,0,0,0,-1
+45efbc7cc2657278f878bc973cecc141,88.6816,313.237,68,15.2853
+45f4141cfe3f110f9db4e1e113d15684,0,0,0,-1
+46199ffd681fd429aca3823c76f1034d,0,0,0,-1
+463b67fefdde16ba3c4a4258de1f38e3,0,0,0,-1
+479078cdf18cd6b677b79d2d9b075d81,0,0,0,-1
+483b89a4ffbbd85acc8b9af5a541dd4d,406.2036,175.1542,84,10.3444
+4842c8c0a3f387effde44cb9b3d3fd2e,0,0,0,-1
+48713d11ced3c60a531e6e80258d6425,0,0,0,-1
+487cc9003c99fa95e9a9e201d396992c,0,0,0,-1
+48fac79fead32f2b10e37752cb077af6,0,0,0,-1
+493641ef65ee95fe994d4789aec1db3b,0,0,0,-1
+494b9a6714921a446b32959ca291b050,0,0,0,-1
+494c42cb61c1e4a02504c16fe09a8129,145.4186,274.273,182,10.9372
+494c42cb61c1e4a02504c16fe09a8129,135.3205,342.8333,186,9.9656
+49a29b3f5bee32b350bedc4cfbad8e9c,0,0,0,-1
+49b5b3444cf977439600dd06e8dd84ad,0,0,0,-1
+49ee28b71e02be4689e3fb0ba2a32c2b,0,0,0,-1
+4a1391269629d20359325873d11413c9,0,0,0,-1
+4aa3131e76b28e30235664087407edc3,0,0,0,-1
+4aea6c3360cd923d25f33ec5b5e643bc,0,0,0,-1
+4b19444c570185fc4606e4e29fd1ce1c,383.6455,151.229,116,16.4201
+4b2f615f5498ee9d935b0229a2e6bb19,0,0,0,-1
+4b351d0c19be183cc880f5af3fe5abee,365.48,290.5467,165,9.7721
+4b7f72b889e85b479305f8fbc8cc4f48,88.6816,214.4599,81,15.603
+4b7f72b889e85b479305f8fbc8cc4f48,82.5663,291.6627,95,10.28
+4b8e47f2a5edda13b971da27317bfc6f,168.3184,312.2116,134,39.9645
+4b96e8e085d7ab16c8054654fe586553,0,0,0,-1
+4bf6fb574a2ca2da551609e98a573e54,0,0,0,-1
+4cc309d81bf3685d7def772862375a2a,0,0,0,-1
+4d207541fac845d1a369a160f15d55e6,0,0,0,-1
+4d621b0adb6b46b353056e1843621c5f,345.7671,228.3562,110,9.6409
+4d86e1657d46b9ee44c2c434fad231ce,325.1962,313.4491,45,18.3687
+4d8f4de444a1f453e7ad32d067b0f630,388.0888,236.6762,120,19.3345
+4dade0813da186d968b4b8c4952cbb0c,0,0,0,-1
+4e9c2cbf385db44b6f5e6618f47318d9,0,0,0,-1
+4ecf053654c565e4a5d0f37811eade66,0,0,0,-1
+4efa432089851f50a5f53fc5a12e806a,0,0,0,-1
+4f1573f5cab1aaaebff33287682c5fbd,0,0,0,-1
+4f3039ae82f8cc764d1ec21116f54a07,0,0,0,-1
+4fcf8b00ea7a99162dc70aba253ba669,176.9202,134.4366,110,16.4682
+502d4601458807bf0089e6fd07825357,0,0,0,-1
+506b07466777f6c6f4dd50a42896a2c4,0,0,0,-1
+512397206b42f1f8d009113511ae2937,86.2891,285.2103,118,16.5335
+521924ac2f00a62cc63f679de7e599cd,0,0,0,-1
+5253d873ff82e3fa69e30e542d13a4ce,96.34,364.9,40,7.9788
+5275c7ec0f1d80c829611c378708c05b,58.323,264.7267,103,14.3175
+5278093ed7187e1a8be518d954509da7,0,0,0,-1
+529e4dd38822b413a4a87e6f4faa5f23,458.64,315.6,30,12.6157
+53087ef723e2433ad0b8041e408c6f8c,0,0,0,-1
+5368521797323c89292781b8780e45b5,0,0,0,-1
+538600927ec2970552917a29b490b5fd,0,0,0,-1
+53ddfb7769619035ad7f8f58c72f697c,0,0,0,-1
+540dbb66efa0f76499464689756e69f4,120.5208,371.2013,81,13.2987
+54162a514a5e2beb54e4b7aff41f5dfe,0,0,0,-1
+54d421d543e9e6dc8db10066a5867081,0,0,0,-1
+54df448f6c74df6bfa6b75c05393ace1,165.7025,340.9256,149,12.4122
+5518b27f000e34cf2db5a362f4fac613,88.1,195.6818,69,11.8345
+5518b27f000e34cf2db5a362f4fac613,62.7068,216.6316,69,13.0131
+5518b27f000e34cf2db5a362f4fac613,76.9675,192.3338,65,16.3552
+5518b27f000e34cf2db5a362f4fac613,68.7048,216.8857,65,11.5624
+5518b27f000e34cf2db5a362f4fac613,118.9502,248.403,64,15.9975
+552ef3f04be2073d2cf8a52431576c24,0,0,0,-1
+55baceb599dc8aefe4b13c131d0531df,0,0,0,-1
+55d88980822c2e5d39b3d0ec172fa101,0,0,0,-1
+55e476ee19742fc09c4ce5e6ebdc13d1,0,0,0,-1
+55eace190c5917cdfb390ca652149fbc,0,0,0,-1
+565cdee745ea4e6afc0f7daae81a7963,440.687,331.3052,58,19.3289
+566a5d958f17d2fc44d4a1ec00401034,0,0,0,-1
+56995718fdd0a0549d0e7f11eb307f34,0,0,0,-1
+56e0f421b7faddcae027d7feb6dae8cd,0,0,0,-1
+573e900142c9e6e7b32ed9e5ffd5584c,0,0,0,-1
+5765dc0dbc8c02a4c862563eac4950ef,0,0,0,-1
+579dfed23d49414a2c080bbf9d7f958f,0,0,0,-1
+57af0020213d64598ede82fe9d6bb8b3,0,0,0,-1
+57f5dc474b6a35d02542299dd09e68d6,0,0,0,-1
+5818c3be99a83ca8c951ff3434750d6a,0,0,0,-1
+5861f8f8e35c0713c61e8ab3bc54c905,0,0,0,-1
+587d6230f2bad2525c47632fd792a895,0,0,0,-1
+58bac12ccb44919bbd64271f38ee0584,0,0,0,-1
+58bf189f6021ecea213c13eed7484d84,0,0,0,-1
+58e4646cbead2fc4a6a1f86bf806e76f,0,0,0,-1
+591f6b47c1362410e7f4c13afbc99d79,0,0,0,-2
+5968ac45330d7f24b041a73925818269,207.9597,313.3519,203,39.7462
+597643aa6bb96b705eac52e03a307d6d,0,0,0,-1
+59e4985cd165f3abbe888475ce564f3a,0,0,0,-1
+59e4e8889ae68a75227b2bd02c1d1b96,0,0,0,-1
+5a06cb92ba004e2265ab087b5b09e33a,106.5571,208.9571,50,9.4036
+5a57009fcdea02d30d31a47d2454dc29,0,0,0,-1
+5ab68460985d9ed8e952475b402ddd62,0,0,0,-1
+5ae03fb6d9959aa93d1177cfd70cf760,0,0,0,-1
+5ae60d42ec7eb7a79ce9a72967cbb6aa,0,0,0,-1
+5b4f56936ab57ee5b30d8752652ee5cb,0,0,0,-1
+5bb9185543527cd034aa48fc0b623874,0,0,0,-1
+5bf71718aa1bdcada76f0683f8d6b41b,0,0,0,-1
+5c0d992d01e6383d5684b8ac5d7143b1,0,0,0,-1
+5c4c25f93529bf21469f81a0acd5d324,369.7963,371.963,12,8.2919
+5c69c62e94dde61c690563eb3553a561,192.9987,361.2273,56,58.7857
+5d240c6a6d3009e61cb09ce49f641b4c,0,0,0,-1
+5d801b07718dc9a1ad2bf701523a0f74,198.9869,318.1307,71,13.9573
+5d801b07718dc9a1ad2bf701523a0f74,470.2766,319.0039,67,14.764
+5da3dd09c0d0d597287a9a1046cced37,406.4429,208.6247,63,14.2147
+5e21909f11ec07f75460fe16b6c0185a,68.0568,218.2955,60,10.5851
+5e371e8fda27df3e5cc2548868229d5b,0,0,0,-1
+5f383eb9c3d8ea72ddec7e2e874d577d,42.0584,218.5987,50,12.1339
+5f383eb9c3d8ea72ddec7e2e874d577d,355.2429,368.5416,51,38.6578
+5f3b9b59f957fea0a5e8cc506e12652e,0,0,0,-1
+5f4e23c0f76cd00aaaa6e03744bbc362,0,0,0,-1
+5faa4b8d9e86c157b7b16e67f22e7210,0,0,0,-1
+5fe048f36bd2da6bdb63d8ff3c4022cd,0,0,0,-1
+60018d051926d01b38dd16e44159610c,430.9,134.95,134,7.1365
+605d3633c1625b4be151d38aad43de94,0,0,0,-1
+60638c0dcee9e5adfcac3b4f57d1366f,0,0,0,-1
+60a4915d8662dff30dc596ebccb83b3c,0,0,0,-1
+60b1526597b82c98ce96fbe5014c0f2b,0,0,0,-1
+61406252b7c29fbe372adfa953d95199,0,0,0,-1
+61917cf6407e793bc0edb60850009e85,395.6271,214.6949,174,8.6672
+61917cf6407e793bc0edb60850009e85,401.1234,149.4455,103,9.5204
+61c0247462b00b95c4df16edd4486a06,0,0,0,-1
+61ce76681b4a68b8d0f3b724c1e844b3,0,0,0,-1
+62099cb774faa70d28d2c5cb1e235270,0,0,0,-1
+63d907adcf3f12349a0c2c8921d38e89,207.9597,266.1416,104,27.4885
+642c43727eee4bda71c0c30bf5cf1a2b,0,0,0,-1
+645e7f46eb9b834153ecf8e2b2921fe5,0,0,0,-1
+6540e089936a6c9d1f11939e96e6ab18,0,0,0,-1
+654f2095bace27af870cdfcc66f9717c,131.4922,189.0091,94,8.6442
+657dc5d2bf8ea210d912dd8320481068,0,0,0,-1
+65dd5d9d5b894e5f0ac3bd6c1384c46a,0,0,0,-2
+65f596f75eebf7935554eaed3c8172ce,399.2267,224.7867,111,9.7721
+661ffa992ed2c23c37f1e7b82dc834d7,0,0,0,-1
+6629e23c3bdc8dc8161b3caa8a6048c1,0,0,0,-2
+665ca5ce18dd06722a4c4436a85246b2,197.6532,409.7675,117,18.901
+666fad0dca00694381eeec67adc909ec,0,0,0,-1
+6675d3cc20585f44d4c45746cb1002d4,328.0575,408.799,70,27.7317
+66a94647459dd5a13f4336e1421119c5,336.4761,317.7257,57,14.6214
+66b7666912e1d469cd9817a1cade694c,0,0,0,-1
+66cef72d8428dbba31f2ab01abdaf6ca,0,0,0,-1
+66fb40934f0be4b301fe27db7fb62299,0,0,0,-1
+67ccc2ecd7716e1cab05caaedea99f4b,0,0,0,-1
+67e87fa621f2e3e838b1b17a898d5b41,0,0,0,-1
+67f7f74220c08faa756b34cb81b203a5,0,0,0,-1
+6828335aec9aa0d0053ec0949319aa4b,0,0,0,-1
+68a1f729eb1e2a791fe8170ac6631828,0,0,0,-1
+68e905099a1c18242aba55c9901eaaae,0,0,0,-1
+6997b392b28529c9ab67add45055fcf7,469.2593,287.8782,55,15.0751
+699e4f02a11a33930a14b13071d24eb0,0,0,0,-1
+6a08bc7a3156caf9b07bbb1f9b2861d2,0,0,0,-1
+6a7f1fd0196a97568f2991c885ac1c0b,0,0,0,-1
+6ae190bcd3fd9c581db4120f4465d65a,0,0,0,-1
+6ae1b284936accdc4101c6daaaa2e0d3,161.2175,131.7526,53,10.4095
+6af9fecd6807921fa9fe10f0391aa453,0,0,0,-1
+6b4837a316e688d0ba125cc1e545d383,0,0,0,-1
+6bebfec174e8a6e8d4b1653c13fcdbe5,0,0,0,-1
+6c1136ce7fbc5c7b503aa08da6abedd2,0,0,0,-1
+6c56e9802fb6346db58bd5daf160f9be,111.6667,174.125,93,5.5279
+6c56e9802fb6346db58bd5daf160f9be,333.4148,347.9559,148,17.619
+6cf71f5017945c9dd8bc0f5126eeef5b,0,0,0,-1
+6d01b46b619b9f6d8c78dbd3f6864372,411.0949,243.1069,186,9.5894
+6d01b46b619b9f6d8c78dbd3f6864372,419.7784,290.1364,84,14.9696
+6d38cc9a6de069570a5d2efbb55a7f63,98,334,135,12
+6d75fe2462284150249a04d78781189e,0,0,0,-2
+6ddb331865608b8dfb8cac6d873eaf62,0,0,0,-1
+6e3a7f8ef70e26252d25cc105a945f86,204.8408,355.9918,34,11.3773
+6e5f12931ef179cc21382a59f5acab86,0,0,0,-1
+6e6d5603fb8fcf523f86ac0856e50236,0,0,0,-1
+6f38eb7988753c6a978d0da80dbc014b,0,0,0,-1
+6faabf4152bf0ebfd91f686bc37a1f16,0,0,0,-1
+6fd582d25eeb2250c2b0996c4216deb9,0,0,0,-1
diff --git a/training/detector/labels/label_job4_2.csv b/training/detector/labels/label_job4_2.csv
new file mode 100644
index 0000000..fccab80
--- /dev/null
+++ b/training/detector/labels/label_job4_2.csv
@@ -0,0 +1,575 @@
+id,coordx1,coordx1,coordx1,diameter
+700bdc2723c2ac75a8a8376d9ca170ad,0,0,0,-1
+70287a7720e0d90249ac7b3978b7ca40,0,0,0,-1
+7050f8141e92fa42fd9c471a8b2f50ce,0,0,0,-1
+7051fc0fcf2344a2967d9a1a5478208e,0,0,0,-1
+7180c83eb184d5c9dfcbda228ab91213,0,0,0,-2
+718f43ecf121c79899caba1e528bd43e,0,0,0,-1
+71e09cd11d743964f1abf442c34f2c9d,0,0,0,-1
+722429bc9cb25d6f4b7a820c14bf2ab1,0,0,0,-1
+7239b3a904f39b25c4e303c10a24621a,0,0,0,-1
+72609c2be68be9d7c9cde3d0127c05ac,0,0,0,-1
+72a1e35c34052e163f61585ba0c9daf4,0,0,0,-1
+72b080b50118e9ddb795890eb1f13684,111.2397,144.0514,104,10.2537
+72ed4046708e5607eb0a5703905438ee,184.7243,109.1889,47,36.3905
+73280f6a624b3bf7a766c70b31dfc56b,0,0,0,-1
+7367ede966b44c6dce30b83345785671,0,0,0,-1
+73b28e2eadad587c9a8ac6c7186dd51b,324.4242,220.0303,110,6.482
+73b28e2eadad587c9a8ac6c7186dd51b,114.5333,376.2,85,8.7404
+73b28e2eadad587c9a8ac6c7186dd51b,300.1961,237.4118,113,8.0582
+73b28e2eadad587c9a8ac6c7186dd51b,194.3889,357.8611,111,6.7703
+73b28e2eadad587c9a8ac6c7186dd51b,0,0,0,-1
+744bb5ab2a706c8070a3f5cd72848ccc,0,0,0,-1
+7471f583e1fb0e34d9e582c313af4358,0,0,0,-1
+74797049e8df8ed38947fd38840b539d,0,0,0,-1
+748bc72733efdabb4c239afb612bf7d5,0,0,0,-1
+74b3ef4c2125d636980a19754702dbb9,0,0,0,-1
+74b542d34b61740c1933d2c953403aa6,173.787,228.4733,89,18.047
+74b542d34b61740c1933d2c953403aa6,86.2687,301.3881,70,9.2362
+74b68f9442209bace31aa62027fbb79a,0,0,0,-1
+750680cce371800ea26576b694b32dc8,70.9085,309.8191,124,23.362
+750680cce371800ea26576b694b32dc8,327.2503,423.9766,94,11.7607
+750c11a0a87833e0bb26441b52b51399,0,0,0,-1
+750ed950a05e5fae10b4d25ed9bcd021,0,0,0,-1
+7525f0ec0999007a0bac946e346eba39,0,0,0,-1
+7577cbd6961b0cab27f88727dcd2d6d3,0,0,0,-1
+762d3d698144370d197a7b9bc978d6c9,0,0,0,-1
+76a77d945cd4c568f3b602957e1ec031,0,0,0,-1
+76e54792d7f5543f734e0906ea8f36c5,0,0,0,-2
+76f36ea4858c572b425eb915e1b27c8d,0,0,0,-1
+77941d758eae521a00ef225e306eda08,368.265,202.4973,132,17.8255
+77941d758eae521a00ef225e306eda08,226.1579,203.2237,114,9.837
+77941d758eae521a00ef225e306eda08,177.2049,263.6776,99,11.8004
+77941d758eae521a00ef225e306eda08,187.4586,327.5921,88,10.4344
+77941d758eae521a00ef225e306eda08,219.9286,361.771,75,12.97
+77941d758eae521a00ef225e306eda08,408.2543,334.0861,74,14.6292
+77941d758eae521a00ef225e306eda08,66.8071,281.7924,72,12.3044
+77941d758eae521a00ef225e306eda08,67.8324,255.1328,66,18.0987
+7797bfd33eb9f06da2b2f5d5c6501af4,0,0,0,-1
+781cf9cc66e59f4586d9338630b95c1a,0,0,0,-1
+7852cb521d7029ca08133476054e7bec,0,0,0,-1
+787bd094dd0586ea0f51f9f8557424a8,0,0,0,-1
+7921bbb92d5390784f3ba046be0d59a3,0,0,0,-1
+797d6bffdecfc88e990e820dc5771a0b,408.3231,155.8,52,9.0973
+79eb6f0a80841d6618968362dfb1f57f,351.5174,367.5814,54,18.4693
+7a705cc36536145911a2ef9ace7d9930,164.7945,140.1438,58,13.6343
+7a82802a862a267d58aa2171645f1181,0,0,0,-1
+7ae953bb9e0356d2990ee6655c8bd168,0,0,0,-1
+7b24367c58f1737e901dde9a934d1eb1,0,0,0,-1
+7b43882369098df840e51421e6059aea,308.604,352.396,204,11.3401
+7b4d476d9414c9339269efe47840d2da,0,0,0,-1
+7b547c5afa0c028b0e20e9a28eaeaa41,0,0,0,-1
+7b6c63074678f65784bdc54d8d385b83,0,0,0,-1
+7b72b604e0af8decb22021cdb92927ae,379.5441,393.8992,116,24.2742
+7b76426f64cb4fbe3d4caa1dcbf47a2f,0,0,0,-1
+7b84056d69644df2a9452a1746d14d39,0,0,0,-1
+7b87e500ff88c264aceb67cf57b32d6d,0,0,0,-2
+7bc437435c5677d361177adb80547bd0,0,0,0,-1
+7bcecfdddd3bd47e3b36ffb05bbdab60,0,0,0,-1
+7bd3565827be855caf938e72b3a7880a,219.245,259.5761,86,10.2537
+7c8aa548b813dadf972c38e806320179,0,0,0,-1
+7dbc5207b9ec1a1921cc2f03f9b37684,0,0,0,-1
+7dc59759253943ac070ab2557c219731,0,0,0,-1
+7df28e2253be3490208ba9a9f470ea1d,0,0,0,-1
+7eb217c0444e5d866bd462ade5266a06,0,0,0,-1
+7ec258e536a1e0353375295ad1b71e5b,153.9063,280.8281,110,9.027
+7ec258e536a1e0353375295ad1b71e5b,276.6656,343.998,80,9.953
+7f45518a2f938a92fa99658d98770316,0,0,0,-1
+7f524231183ed193b8f2e3d9cc73c059,0,0,0,-1
+7faa456389e1ffde464819d0b1360188,416.4381,341.2762,134,11.5624
+80588b9231bb4fb7e1cddc9321d12e76,0,0,0,-1
+809ae218d8b4a973d11358264e4a0823,0,0,0,-1
+80e01dfd642c5aea680852498ddabd28,0,0,0,-1
+81528d5c9ea936264bf9aa8ab4f0ea5d,154.4974,354.4031,104,15.5945
+820245d8b211808bd18e78ff5be16fdb,0,0,0,-1
+820cc2a44d87d9b3798782f7cc6f2a74,0,0,0,-1
+82289d2db2b1e33d68ba6736b21b0e43,354.9352,242.1449,87,12.5488
+8269e2eb69b3ba38c48dd5ae6039e250,208.1649,377.2784,73,11.1132
+82df9b029653e867e86ce9e86ca7275c,0,0,0,-1
+83463d2951670b7e8c3efd7594a13e10,410.6469,129.6963,67,28.5552
+834dd009c49e7faaf8e4caba668a2d8f,0,0,0,-1
+84402e42c992259ac8cdd98b51d4fba3,0,0,0,-1
+844032970cb66839f748512acba0be8e,0,0,0,-1
+85059119462b510aacb6da54983addcf,0,0,0,-1
+85746d90494345e38ab61533e999b3f1,344.6816,303.6669,143,16.0167
+8589428b683d33b99557d7d3b43a518c,0,0,0,-1
+8615d91dab90b906088e4097fc822820,0,0,0,-1
+862d1d80391d146b2cd02478a798b365,0,0,0,-1
+86515f063b3a30af09ba4d0322edf7b1,0,0,0,-1
+86ff28a92989348192783795a5b442e5,109.8725,172.4199,97,8.7541
+87b81bd007c5b23cd0c0aeca722fe52f,0,0,0,-1
+88be713eb83cec7d31c4553ca05b2019,0,0,0,-1
+89629540f3b3cbc2a18d9919facd34d0,0,0,0,-1
+89960d9a801625bf76e9e1047acc5cd5,0,0,0,-1
+89fbce8f7fe8ecc1bf7067a292c7ab2d,308.4718,178.1694,108,17.7697
+8a17bbe3cc0079c6d7d7579359bcf565,0,0,0,-1
+8a1fa06a0099522730dd3c12c9b9cc78,144.4186,131.093,62,7.3993
+8a2de07f6e9dbb8c6e4bfad7e83b3f0a,0,0,0,-1
+8a8419bb3048294f69a31de36cd35a98,251.715,166.9513,155,23.4916
+8aaa3a09b1f20e950609a62a1de511df,0,0,0,-1
+8ad1af382994ce945a5034fab202d402,0,0,0,-1
+8c22afe3214768d4c585580a2364614d,338.025,373.7625,36,10.0925
+8c2f9e7025d6070e9f4ab8a65c8e9dbb,0,0,0,-1
+8c4d81d9d24d9d66e9ced5f40d07960a,0,0,0,-1
+8c5288b86ffcd597f10d639e9948411d,105.0874,206.257,118,26.9385
+8c6f2ce60479f73c257173911aff3453,0,0,0,-2
+8c7b03ed7f61c7faa5a26e126d769404,296.4893,377.8351,36,21.8852
+8c9925cf3627cd4742bbc8677f905afc,0,0,0,-1
+8cb4c49a88d8ecb99d97cf5d707d58d7,0,0,0,-1
+8d5c4cc78e964463699c19003be70851,0,0,0,-1
+8d98bf96ed8555da4df44f26cc8426bf,0,0,0,-1
+8e0624a689e8e02dbae149771f51f8ca,0,0,0,-1
+8e7638040431e1d91dffa4497f7078d9,97.2263,277.6909,44,23.4916
+8f0c4220a437192a30ae06d82bf78885,0,0,0,-1
+8f0d9699a15acef00da458eceaf0c846,0,0,0,-1
+8f28d220d960b67f799479f319373c21,0,0,0,-1
+8f4c97d428c70831d74660bca08961b9,366.2316,257.7684,124,26.9397
+8f6e50767b3bc4367bfe551b0ed73773,0,0,0,-1
+90604d9cce6ab054664c8efa7ce61b20,0,0,0,-1
+90d6324d7006a3d142ee1884279dcf9b,0,0,0,-1
+9109609020945cfc237125dc5f43f7b9,0,0,0,-1
+9139a5b2f18c79a75c2d8ee817cc2495,0,0,0,-1
+916ab7b22affc5651abfc9aae01bb355,0,0,0,-1
+919b9f74bcee297abd6e217d185a025d,0,0,0,-1
+91d0606b85ab7dbc7bab718c1312f2df,0,0,0,-1
+91ee390b30927af8804d1f2adf2aefa8,378.4952,381.1619,134,11.5624
+92286959d1899e9b480d29c545cb1e0f,0,0,0,-1
+92d5f6230c3b6f6256e57d30981c1aaf,0,0,0,-1
+933cc0dec1c737d9654820453ce64284,369.2904,315.2877,87,21.8852
+934bc93ae41ee1d98c7c44d483327f8d,0,0,0,-1
+934f01786c3bdf8eeaf7d8411a3a8f82,0,0,0,-1
+935908ab6e4c329756638887f2dedca2,0,0,0,-1
+93b60dbb5cc3fa4c4cc9247cb1143a09,0,0,0,-1
+9437f7c26ffdaca5a9ae5302d9736c35,0,0,0,-1
+9462c59a652187dc2d581b8772bcb3f0,0,0,0,-1
+94cd77da118cc1d667cd9732853f0c48,0,0,0,-1
+9560214767e1257dc97c5103a27f1d2c,214.8017,207.2824,73,8.2314
+9560214767e1257dc97c5103a27f1d2c,72.6175,274.273,54,6.8699
+9560214767e1257dc97c5103a27f1d2c,115.3411,219.9286,58,9.1966
+9560214767e1257dc97c5103a27f1d2c,343.998,423.9766,49,9.2977
+9560214767e1257dc97c5103a27f1d2c,97.3684,264.7193,69,8.5191
+9560214767e1257dc97c5103a27f1d2c,66.8071,296.8311,49,8.6467
+9560214767e1257dc97c5103a27f1d2c,303.3251,379.8858,43,4.158
+9569bb8d5fc4461461078b2e2ca29f1f,0,0,0,-1
+95edad4544e59e37188dd33db40cecb7,0,0,0,-1
+9626af3a0a37c4fa5187447f01aa69da,0,0,0,-1
+965fbaad39ecdaf8a135f022c8ddaef3,314.2623,343.6562,98,22.8462
+968808e60982c76366088b4db7254671,0,0,0,-1
+96dce4424dce5451ab0a068c58435c1b,0,0,0,-1
+96fdfdfc4417d5bf8e6750edbac8ff90,0,0,0,-1
+9759889dcee7ed0043d06e03fb44060d,0,0,0,-1
+9759a365f7a8b828e964b0a53cc2daf8,0,0,0,-1
+975c90ab2afd216efbb6b772a22ba3d9,0,0,0,-1
+975f7f3c5bad9e9f0bc31e723fd6f793,66.1235,336.1368,72,27.893
+97967da068bd4ee2d9cb7558f1d8c18c,0,0,0,-1
+9842a3b9dfabab4ae8642d9953058ce4,0,0,0,-1
+98bde8f061ae92dd23b0708fdf41381e,0,0,0,-1
+98ea0b7d586e5e888e31633772f4df94,0,0,0,-1
+990fbe3f0a1b53878669967b9afd1441,0,0,0,-2
+991a2fe88aeb9ef23bb011e3843c9105,0,0,0,-1
+99579bbe92d0bb4d5cd98982305870af,0,0,0,-1
+99ce8aa6c0afe0e418f49823f8639776,441.0661,195.6615,78,27.3517
+9a5c2aa17362a58ae8adcb4e0a46c7e0,377,225,282,6.8637
+9b259149a750af0c21640624e4be964a,0,0,0,-2
+9b4f0020e407fd7f980f4241fb6ac7ce,0,0,0,-1
+9b797e680158d10e5ae2f9166c1dabb4,0,0,0,-1
+9ba5fbcccfbc9e08edcfe2258ddf7178,0,0,0,-1
+9bf3ca649999bc6856ad9f01c64eb7e4,0,0,0,-1
+9ce92cb785c9878389bd5f765a07e1ae,0,0,0,-1
+9d44fcc8ab801ac9244da4c016d0541e,381.5556,149.7071,130,11.2272
+9d453de54a141820fcf62bed9a53540d,0,0,0,-2
+9d89b32f7dea356b2d35cead7bc94d80,0,0,0,-1
+9db8f95c3240b79c32af0c0bd367dd91,0,0,0,-1
+9e249726076fa41af6766e12957a7e9d,0,0,0,-1
+9e471e15d44721a48d8b5f4b0a160dd6,213.7764,402.4439,100,10.3444
+9e680611b54f8fad7acf818b15385002,420.9005,364.5053,181,8.6467
+9e680611b54f8fad7acf818b15385002,93.1248,429.1035,110,8.9128
+9f12d2d6134af032932ed37776c6d09f,0,0,0,-1
+9f19c381184ba62416025849c464630e,92.4413,287.261,91,26.9732
+9f49140c0447a0c3108ba3591b11958f,0,0,0,-1
+9f73628a5e06cfc6723f3ee2ae4b96c4,296.4893,107.8218,148,22.2662
+9fc639cbbd749117de4980420ae52cf3,0,0,0,-1
+a01074fefbae0234398c365adf970118,0,0,0,-1
+a0cdb677841933136fd15257e3c47fe6,0,0,0,-1
+a187b24f9827de759fb86a84e9b2e544,345.7143,168.7293,79,13.0131
+a1b021261acaa7ffedfe15d2c8380de1,0,0,0,-1
+a26bba2936f12f19893e54b40e0759fe,0,0,0,-1
+a2c59fd551d9c658f8469726b66bee87,0,0,0,-1
+a2f41e283f3c797e85c0b9d63453b365,0,0,0,-1
+a2fc15125f7e222b3d8d579167f4fc95,0,0,0,-2
+a2fe50d59500281851fce256e922b675,0,0,0,-2
+a305389fe87d54597dfad222e47abac5,0,0,0,-1
+a3cb12d3b8d5c64fa55f27208fe13a07,0,0,0,-1
+a4ae73433e63549558a3d0eed9128a69,0,0,0,-1
+a4ebf3e2861b7845845bad3bacbbaeb5,0,0,0,-1
+a4fa7dd73e3017b97ac6674a10fac216,0,0,0,-1
+a590753c175011e42bf17b90e3aec3b0,0,0,0,-1
+a59b1dc7e417fea605b34a5204f61f9d,0,0,0,-2
+a6195eb9162fc40d5fa2fdb1239dd788,0,0,0,-1
+a647d0ce63b01c9ee82fe1911ba7b1e5,0,0,0,-1
+a654285bc604830f627687fa821d7dd3,0,0,0,-1
+a6b7aa6b98dd87cf75a5e1f707369832,0,0,0,-1
+a6efbb642c60022fe194da17d71a7fb3,373.0501,166.2677,139,11.0224
+a6efbb642c60022fe194da17d71a7fb3,142.6842,141.6589,94,13.6716
+a6f09ff7b85c72ee28a9e725bb1ec652,0,0,0,-1
+a7293f9b20e715fc78cc0b09a4feab01,0,0,0,-1
+a73f098ed638571f8db71a20e1551875,0,0,0,-1
+a7411bdc623413af46a30bd9d2c41066,0,0,0,-1
+a79023a82079a7431ef2496acbef29de,0,0,0,-1
+a7eca254c634f5f6e3cd0e508b069f1c,0,0,0,-1
+a83542b34be44586e8c9f96f4fa180da,0,0,0,-1
+a858e3c7cf53e0996d76f57f2210c59c,0,0,0,-1
+a87740afc072074e6c5a2ab787235dde,101.6696,234.9673,90,20.5187
+a8d308b966048be67f7413daf952ee94,346.9312,190.6714,70,14.1054
+a8f2ebe1d66b24741cac1eb465a2ff72,0,0,0,-1
+a906cd7c6ad05c27216125485d2b7322,0,0,0,-1
+a93362de52065e73e6882f0cb668d637,0,0,0,-1
+a998534bc46d3041e00c67f44a3e0352,0,0,0,-1
+a9c1d12dabcd5f5b13d2aad47e443684,0,0,0,-1
+aa198aacdec142168b8de04c4444054e,0,0,0,-1
+aa477f5b9ce7ab1e886e474be5397727,0,0,0,-1
+aa528ce110f888679a4027513aeb442b,113.539,357.2377,114,9.885
+aadd54d387e9be8fab53507c4cedf338,135.9118,335.6275,147,11.3961
+aaeb75b838690ba6ba425f73b9773479,415.277,325.3176,48,19.4134
+ab5de6c17f4086ba09b7145178d83b45,0,0,0,-1
+ab9e5f1718f2af09030dd33b531f066c,0,0,0,-1
+abc4cfb4ac045b4f9a74e2dbb18f8193,70.0515,286.0515,75,11.1132
+ac4e4bd5633dd74c99762acdba21934f,0,0,0,-1
+acbb4e34904af9781fe089f586418a21,0,0,0,-1
+ad5f3a8ee73c1ff4cf401746be3bd493,0,0,0,-1
+ad914d487aae66bcc2a7760a959d8a7c,0,0,0,-1
+ae42429e25ce48034baa3dd527c7810a,0,0,0,-1
+af2b9f7d489ffab8e3590658853cacf8,0,0,0,-1
+af3657cf479490d027ada92b330f80af,0,0,0,-1
+af7420c5b1c47763ecb5f6e286517b2e,0,0,0,-1
+afc15e047f3e127871d13e39cde7557d,332.4493,354.7681,109,29.6401
+b06ccf39536d0e3e0e8c78ba599ed23b,0,0,0,-1
+b0864a9fd01ec7c7fa3a8301bdb2d03d,0,0,0,-1
+b0d5ba3a5ac7998791f7e484c070dcb9,0,0,0,-1
+b1184cbc6dfa46734807211f95f3c998,0,0,0,-1
+b1786f35f31c424f6c9e3380c1c51c0b,0,0,0,-1
+b227e1ab3efc4b3c5148a614d01edf50,0,0,0,-1
+b280f1f464aa5e0de843229de12fc1aa,0,0,0,-1
+b2d6eb577e716ade61ca89b6bb3dcabb,0,0,0,-1
+b2f99ba5baa498246add63b1acf62cd4,359.5649,358.2351,115,11.3234
+b3854df98b8325a98f7b48bbaf24bb02,0,0,0,-1
+b3c2d92976acd67a13493cdff1ec33ce,0,0,0,-1
+b3f57de0b4ad4dfae87698ef8fc67e23,0,0,0,-1
+b42263b9b84f10464a94092e0cdc13b1,0,0,0,-1
+b4581f4f4cad292b5a013d35d1c39f24,0,0,0,-1
+b4d7268f5a8436da6634e585db3e9478,0,0,0,-1
+b51f22a84cd2fae1de8bd1eb155933f7,188.9516,378.208,55,21.1402
+b53168fc0e9800e06de66f53daf9c5f9,0,0,0,-1
+b5c041f7d841532ef778fd5e71309cc2,0,0,0,-1
+b61b1911d3631bee521fcda3a3e568a1,0,0,0,-2
+b818f0244d2adb13520191eed99e4680,0,0,0,-1
+b8276dbece0182602d2ae0c825dfa1b4,0,0,0,-1
+b844a9510fc4021d9603cdf24cf0545b,0,0,0,-1
+b887defbf88deb3c6fe4c22405d0a957,0,0,0,-1
+b8ad1b45ae4ba6c97951ed30b8640f6b,0,0,0,-1
+b921bb8f821ccab27ab69ea94b8149a7,0,0,0,-1
+b947a27711c94dda2d13e7410285cc0c,0,0,0,-1
+b997943f8b95d72ca9a3c36f5c695412,0,0,0,-1
+ba05599872742ce748e2eda745e51857,0,0,0,-1
+ba162711fc958842582ef1828d37f8e0,0,0,0,-1
+baafc60a08ae90052fd44eb78a21cfbf,0,0,0,-2
+baf842dd446ce9d7082efe16d22fb971,84.6143,381.8403,43,32.926
+bb0a8375885408a7adbd7c941098548f,0,0,0,-1
+bb8393e219a2d5e3f8a183da638cc210,0,0,0,-1
+bba773fb9c1c517e23efe05e283b58a2,0,0,0,-1
+bbed0d350caad0e19e5b0fc858097ce4,0,0,0,-1
+bbf958c2331a553d5699a1369b7f2bbf,0,0,0,-1
+bc28807c545959c0e6e2708067201caa,0,0,0,-1
+bc43e8a2cb05a45e73dea8c7e02f2cc1,0,0,0,-1
+bc848c4d50c2f72fdcc1102475b56525,0,0,0,-1
+bca9f24f465ae61a03e35a1f682270bd,0,0,0,-1
+bcb416e94f3505c120a54dbfc0d5a234,0,0,0,-1
+bcc701884a32d8883b73b5844241a354,370.2039,260.4896,275,18.5468
+bcc701884a32d8883b73b5844241a354,151.4403,376.5208,165,13.6433
+bcc701884a32d8883b73b5844241a354,140.4688,145.7883,128,12.546
+bcc701884a32d8883b73b5844241a354,224.2506,262.4844,96,19.4202
+bccbc10909a55c0f654719e8839f530a,0,0,0,-1
+bd702368c252929cf701ad56ce64b6e1,0,0,0,-1
+bd87def5b7e1ec4f0057cde049995d83,82.1026,197.7179,60,9.9656
+bdb59c956d48bc1a263acf997926c4d3,0,0,0,-1
+be024b0b5cf93c597758e65f348475af,0,0,0,-1
+be57c648eb683a31e8499e278a89c5a0,72.9779,328.6455,95,15.5231
+beb2f21fa785f088469a4530784e9d81,441.8419,206.3088,86,18.6097
+bedec8e1ad130a08faeec8ed81780d56,0,0,0,-1
+bf1c730d11f5c1db7da7c39808451c4c,125.5078,338.9519,39,17.6678
+bf3dbf9b2379ca92ceaafc1867de0422,0,0,0,-1
+bf56e271a2aa37625192954157e9f64d,127.0182,207.8727,175,11.8345
+bfb3e2d11c149036bbe12566ef6b933c,0,0,0,-1
+bfdf6f821031435d9a397afe001ad774,306.7026,334.6299,121,13.2987
+bfdf6f821031435d9a397afe001ad774,160.4169,187.0143,115,8.4108
+bfdf6f821031435d9a397afe001ad774,384.8523,232.7273,116,10.5851
+bfdf6f821031435d9a397afe001ad774,155.3586,332.7448,95,13.5875
+bfdf6f821031435d9a397afe001ad774,87.274,292.4065,118,11.9873
+bfdf6f821031435d9a397afe001ad774,89.2688,278.4429,111,10.6597
+bfdf6f821031435d9a397afe001ad774,364.2195,269.1338,133,11.0066
+bfdf6f821031435d9a397afe001ad774,196.3234,352.5831,105,16.0138
+bfdf6f821031435d9a397afe001ad774,175.0455,364.5519,107,13.0977
+bfdf6f821031435d9a397afe001ad774,124.5104,317.0091,97,7.7829
+bfdf6f821031435d9a397afe001ad774,426.7234,301.0506,90,10.344
+bfdf6f821031435d9a397afe001ad774,136.8542,336.4653,91,13.5406
+bfdf6f821031435d9a397afe001ad774,135.8143,372.1987,91,9.5204
+c004a9415539a0bc98c42c1a444cedb8,58.0169,281.1026,28,21.9429
+c0279b938ac1790f1badfcd4459f5c4c,0,0,0,-1
+c02daa2116b27ce9b023fe7809ef5be9,0,0,0,-1
+c0712bc73239d89cddd71a93865e2946,0,0,0,-1
+c0a71c28edac0a4bbdf64f058903c4b4,0,0,0,-1
+c0f2e3b499d10d147892579d0ad71321,0,0,0,-1
+c14816a1a9a6852c6b0d88fe5585c8bb,0,0,0,-1
+c187d7be84f64e29e6623c15575f373f,0,0,0,-1
+c19197af81f94110ddc23317e182f37d,143.1286,348.926,187,42.789
+c1ac4b0949e6e7557f82caf20761322d,0,0,0,-1
+c1f5ca42b0e336a7ab85b4c437b382c0,0,0,0,-1
+c24798432bb6a0d4c80df831b8e09246,0,0,0,-1
+c24dfc6534bc563d5aecb1513fea8f7f,81.6221,265.4766,41,3.3247
+c24dfc6534bc563d5aecb1513fea8f7f,82.6195,254.8377,32,6.781
+c278a6dc82c323254ff53c58db759908,0,0,0,-1
+c2878958469b61d4f4406bbe945f8bd7,0,0,0,-1
+c2af7c1d6159ae152a79f32d88c33ab2,0,0,0,-1
+c313167b76fb2528816d40088ba88c77,370.2039,308.3649,77,11.7827
+c31e3540b227a1a2b08593094609ece2,0,0,0,-1
+c3d37bdb061c189269f4223f8bebeae0,119.6591,265.1705,95,18.334
+c3e23e84b9f9f31c3ba5458c7f43ec52,466.6195,198.6506,29,8.6697
+c3e6b43c5ac3f4ac052e0b0421f5b088,0,0,0,-1
+c51d53068736c39d56b99074d2e29e12,0,0,0,-1
+c545ccf3a5128fdc313ed936f61658a6,0,0,0,-1
+c590651cdf70258ffb1b6ee18da6a1b2,168.7286,166.0688,47,6.0212
+c5f73cf44d785e5ac2e7f0a8897f683c,0,0,0,-1
+c6269c87a7571330961e5c4a9f692c10,170.0584,247.5234,110,4.6545
+c645eb8b7b7225457e61cf511a8e46e5,0,0,0,-1
+c65cc99faea7d0f79c175460c712f375,0,0,0,-1
+c68ec9a72b87f4bb7935534182145733,0,0,0,-1
+c690f27c439a58684910d04d6409cd17,0,0,0,-1
+c6b722b00948587dd89a548f9639f447,0,0,0,-1
+c6ba816fd9c99c11ceb189ac24d2d2f6,0,0,0,-1
+c713ec80637677965806579fce0b7dca,0,0,0,-1
+c7b20bdbf5f057ec1e9706ca43bf9a2f,346.2662,367.8766,47,20.613
+c82d5bc4554358b1512f9f871822705b,0,0,0,-1
+c84e28d37dcc14a268b760bf16213cfa,0,0,0,-1
+c8594cc837b12c612d8b9a0913240f8a,0,0,0,-1
+c8a82a4e7e76702f5f10ece6508f2bbe,0,0,0,-1
+c979fbec565e769de7e66944ab5365a4,0,0,0,-1
+c98675ecb5bdc7eb35c69d730da05df1,0,0,0,-1
+c98fb8f387c0979531e11de53607de92,0,0,0,-1
+ca3cdb2e771df9989df5a9cb0296c44c,140.4688,338.287,82,7.4342
+ca3cdb2e771df9989df5a9cb0296c44c,109.2169,166.0688,77,5.3609
+ca3cdb2e771df9989df5a9cb0296c44c,77.9649,137.4766,49,8.6442
+ca4e1486c548679a9c682b6fa1a779d9,0,0,0,-1
+caddd8f856b110ed9bb52872e003193f,0,0,0,-1
+caf38dcf62fe3a05fac40055920d7058,0,0,0,-1
+caf5e9cd994c3c90727d274dd790133a,0,0,0,-1
+caf9672e7177c141dd3d9c8631af6b8d,0,0,0,-1
+cb0110b3780d2cf1134221404b82713a,0,0,0,-1
+cb8d3452b667596fbf132d2ce9ebd0e6,160.1339,368.4409,112,12.7162
+cbf5f53f3648de7d1324257caa40bb90,0,0,0,-1
+cc1bf5250466173086887675dff499c3,384.1675,361.2273,29,4.6545
+cc24c86f88a9d17c04255a4d264030e6,0,0,0,-1
+cc31a959bf4c2a6de3a67dfa378a261c,0,0,0,-1
+cca8f8cc51b58df2a4804a7aee8eef8c,104.2299,137.8091,82,4.2577
+cceb1ae43615e5f144e31d1d1ebbdf90,0,0,0,-1
+ccff3e86a50624e30c22d674f3b0f9aa,0,0,0,-1
+ce0609052ba7b533e2974728b0c76bfe,0,0,0,-1
+ce8b0816304e079bb99c6c25b4fa4b88,0,0,0,-1
+cec6819833f63e96fc3e17e29c0124f8,0,0,0,-1
+ced4f41abff9290b0638b0a25cd5a26d,0,0,0,-1
+cf3034c8828df3c2c23fa697ffde07fa,416.7494,269.4662,94,24.6026
+cf34926681dbf1129cb0a629fb72681b,0,0,0,-1
+cff7e7e9f8cb7b37c109ed6b1f11b783,0,0,0,-1
+d00ee8f03fb00562b2db35e90536ffc1,432.1695,296.0339,151,8.6672
+d08383958039c53ea3347ce1719be43e,0,0,0,-1
+d0baf38ff8d974e7b59c23fd43713de9,0,0,0,-1
+d0c1c175814c610bc333080152a605f7,0,0,0,-1
+d0c86e0c3b3fe3e1dd936b7553ecc29c,0,0,0,-1
+d104e584e51830ea51ee60e69186f83b,0,0,0,-1
+d13d9be7873c99a9fde9d24a95f1590d,0,0,0,-1
+d2282b0eb61b8d3b090cf8eb76776529,0,0,0,-1
+d2285c33945ab3421d753b4fc59ac3ce,0,0,0,-1
+d287819450e57ae8c883ed31dc4dc3a3,0,0,0,-1
+d2a17180c72ce7e5e9cb3870ba7991d2,0,0,0,-1
+d34741458ed4cf1ef6bcf3da21a0c47c,0,0,0,-1
+d36b2cb1cac4b31476c6f86eb1227d3c,0,0,0,-1
+d39d18ec79c7303a61f778f470d439ae,0,0,0,-1
+d3aad463ed33cb02334f0c3029db4587,0,0,0,-1
+d3eaad692dc96b1a1765076716f55421,394.474,370.8688,66,41.9963
+d421129acf503e770dc1575c1b959607,0,0,0,-1
+d4307a302483bcc04717ca4f565db678,101.8493,320.637,72,13.6343
+d4307a302483bcc04717ca4f565db678,150.1104,285.4247,55,14.6437
+d43c9dd1be361b9302c9343af09cc23e,0,0,0,-1
+d4e5c5bf1871b85914168ea12ed579a3,0,0,0,-1
+d51dffd06b80ed003aa6095b0639f511,0,0,0,-1
+d559c9b1f2be30c82f8dbe4d73d67bd2,0,0,0,-2
+d5c43054ba0f66d5017a8ddfde8c8c34,0,0,0,-1
+d66d6279f6a55d7263e2700749b4293b,0,0,0,-1
+d68bfca920fd548909bd9c7eb5694b9d,0,0,0,-1
+d73264d2c4f71ef6bf8593ac55565d93,0,0,0,-1
+d73fda3be1180e4465df6fbef8a0648d,0,0,0,-1
+d74af71db9023b65737ee37ede219422,96.9156,230.9,100,7.0684
+d74af71db9023b65737ee37ede219422,396.4688,414.4221,31,17.0306
+d809c513476775193aba29b31d0050c6,0,0,0,-1
+d81ab3ad896e4198caed105c469a4817,337.6221,384.1675,55,14.354
+d89499632a4c7bde0923003497ffc5ea,445.3416,267.4714,58,10.8244
+d89499632a4c7bde0923003497ffc5ea,65.6636,311.0247,49,13.0639
+d89499632a4c7bde0923003497ffc5ea,65.6636,159.087,48,7.1924
+d8a0ebe575539c2357c2365cdf0229a0,402.8,174.6485,69,14.4943
+d9543b86db1c662ebaa71557e715861c,213.6117,380.8429,91,6.273
+d987c00ec5463a0a696991b72d934512,0,0,0,-1
+d9ef71a00fd504eac1a6dd104c93ce56,152.2217,228.0985,115,16.0769
+d9fb9617188fe99bdb464c126d2bd8c0,0,0,0,-1
+da8fea00d3e921e5d8ab4d90a7f6002f,387.8247,432.7078,61,20.8264
+da8fea00d3e921e5d8ab4d90a7f6002f,389.8195,428.0532,51,20.527
+daaf7680aa9a2b519e53b0e38300163d,99.2619,197.7143,56,7.3127
+daee58dd09c005fe41ca370c2a2fdfa9,0,0,0,-1
+db7c113445db32f9beaf5dc90e7218ad,0,0,0,-1
+dbcb3dbee4f4e75d0672c2a23feb1e3a,0,0,0,-1
+dc1ecce5e7f8a4be9082cb5650fa62bd,0,0,0,-1
+dc5cd907d9de1ed0609832f5bf1fc6e2,0,0,0,-1
+dc66d11755fd073a59743d0df6b62ee2,87.7179,188.359,85,7.0467
+dcde02d4757bb845376fa6dbb0351df6,401.4558,330.9727,69,17.6678
+dcdf0b64b314e08e8f71f3bec9ecb080,0,0,0,-1
+dcf5fd36b9fff9183f63df286bf8eef9,353.913,337.6221,122,5.6812
+dcf75f484b2d2712e5033ba61fd6e2a0,0,0,0,-1
+dd281294b34eb6deb76ef9f38169d50e,0,0,0,-1
+dd571c3949cdae0b59fc0542bb23e06a,0,0,0,-1
+dd5764803d51c71a27707d9db8c84aac,0,0,0,-1
+de04fbf5e6c2389f0d039398bdcda971,0,0,0,-1
+de4d3724030397e71d2ac2ab16df5fba,0,0,0,-1
+de635c85f320131ee743733bb04e65b9,0,0,0,-1
+de881c07adc8d53e52391fac066ccb9f,0,0,0,-2
+de9f65a7a70b73ce2ffef1e4a2613eee,0,0,0,-1
+df1354de25723c9a55e1241d4c40ffe2,0,0,0,-1
+df54dc42705decd3f75ec8fd8040e76e,0,0,0,-1
+df75d5a21b4289e8df6e2d0e135ac48f,0,0,0,-1
+df8614fd49a196123c5b88584dd5dd65,0,0,0,-1
+e127111e994be5f79bb0cea52c9d563e,0,0,0,-1
+e129305f6d074d08cd2de0ebdfeaa576,0,0,0,-2
+e1584618a0c72f124fe618e1ed9b3e55,0,0,0,-1
+e163325ccf00afde107c80dfce2bce80,160.0844,199.3156,123,5.72
+e188bdeea72bb41d980dc2556dc8aafa,0,0,0,-1
+e1c92d3f85a37bd8bb963345b6d66e03,0,0,0,-1
+e1e47812eecd80466cf7f5b0160de446,0,0,0,-1
+e1f3a01e73d706b7e9c30c0a17a4c0b5,0,0,0,-1
+e2a7eaebd0830061e77690aa48f11936,0,0,0,-1
+e2bcbfe1ab0f9ddc5d6234f819cd5df5,0,0,0,-1
+e2ea2f046495909ff89e18e05f710fee,0,0,0,-1
+e3034ac9c2799b9a9cee2111593d9853,0,0,0,-1
+e3a9a6f8d21c6c459728066bcf18c615,0,0,0,-1
+e3e518324e1a85b85f15d9127ed9ea89,397.8898,196.4746,121,12.2573
+e414153d0e52f70cbe27c129911445a0,0,0,0,-1
+e42815372aa308f5943847ad06f529de,0,0,0,-1
+e4421d2d5318845c1cccbc6fa308a96e,0,0,0,-1
+e4436b5914162ff7efea2bdfb71c19ae,0,0,0,-1
+e46973b13a7a6f421430d81fc1dda970,0,0,0,-1
+e4a87107f94e4a8e32b735d18cef1137,0,0,0,-1
+e5438d842118e579a340a78f3c5775cc,0,0,0,-1
+e608c0e6cf3adf3c9939593a3c322ef7,0,0,0,-1
+e6214ef879c6d01ae598161e50e23c0c,0,0,0,-1
+e63f43056330bc418a11208aa3a9e7f0,166,295.5,102,5.7536
+e63f43056330bc418a11208aa3a9e7f0,403.4706,205.9412,102,8.0582
+e63f43056330bc418a11208aa3a9e7f0,70.3182,236.8844,79,4.6545
+e63f43056330bc418a11208aa3a9e7f0,136.3333,259.875,63,5.5279
+e63f43056330bc418a11208aa3a9e7f0,56.0221,294.0688,59,6.781
+e63f43056330bc418a11208aa3a9e7f0,428.5,337.5,60,5.9708
+e63f43056330bc418a11208aa3a9e7f0,151.1852,149.4074,71,5.8632
+e63f43056330bc418a11208aa3a9e7f0,208.5,168,78,4.5135
+e63f43056330bc418a11208aa3a9e7f0,208.4074,333.8148,57,5.8632
+e63f43056330bc418a11208aa3a9e7f0,441.6341,262.0732,50,7.2252
+e6d4a747235bfcc1feac759571c8485c,0,0,0,-1
+e6d8b2631843a24e6761f2723ea30788,0,0,0,-1
+e787e5fd289a9f1f6bba31569b7ad384,0,0,0,-1
+e79f52e833ccca893509f0fdeeb26e9f,0,0,0,-1
+e7cb27a5362a7098e1437bfb1224d2dc,171.0558,379.8455,36,31.1315
+e7d76f0723911280b64f0f83a4990c97,0,0,0,-1
+e8be143b9f5e352f71043b24f79f5a17,219.9286,409.4351,94,15.9861
+e8be143b9f5e352f71043b24f79f5a17,150.4429,156.7597,61,6.273
+e977737394cee9abb19ad07310aae8eb,314.1939,324.2143,186,11.1704
+eacb38abacf1214f3b456b6c9fa78697,0,0,0,-1
+ead64f9269f2200e1d439960a1e069b4,65.3312,256.8325,76,10.7218
+ead64f9269f2200e1d439960a1e069b4,71.6481,289.0818,68,9.9962
+eb8d5136918d6859ca3cc3abafe369ac,0,0,0,-1
+eba18d04b18084ef64be8f22bb7905ca,128.5,260.4896,221,4.0446
+eba4bfb93928d424ff21b5be96b5c09b,0,0,0,-1
+ed83b655a1bbad40a782ad13cf27ce8f,0,0,0,-1
+eda58f4918c4b506cd156702bf8a56a3,167.8406,158.1014,104,9.373
+edad1a7e85b5443e0ae9e654d2adbcba,0,0,0,-1
+edae2e1edd1217d0c9e20eff2a7b2dd8,0,0,0,-1
+edbf53a8478049de1494b213fdf942e6,0,0,0,-1
+ee88217bee233a3bfc971b450e3d8b85,0,0,0,-1
+ee984e8fba88691aac4992fbb14f6e97,0,0,0,-1
+ee9c580272cd02741df7299892602ac7,120.5395,199.5658,103,9.837
+eeb1659b92b00e20bd8b6e7eef6b5c9d,299.3883,243.8662,36,17.9532
+eebd87b91489548bdfc1c76a20999a54,0,0,0,-1
+eed63953a76074dd5ef7360e131f4852,146.4532,388.4896,68,11.2843
+eee8e1b2533abcb73e4b03969a3a5904,0,0,0,-1
+eef0e41b1a96cf8c55723fa6aa2f3dc6,293.0714,132.1571,164,9.9962
+eefc3f380cc72d6fa830972151df01ad,0,0,0,-1
+ef3be197823bfa8c6976ca2621e253d5,0,0,0,-1
+ef6a37afe024d33b4b1bb2fdee054a59,165.0714,373.1961,96,19.0408
+ef8a19fb5314b3222482fa325dd49467,0,0,0,-1
+efd5b9e8cb651e18eba6a9623e36e7be,0,0,0,-1
+f0459473753b99105e9723f122022ad0,0,0,0,-1
+f0f72264cd822301852578cc71288d3c,0,0,0,-1
+f136a3df63637b499704a49fc0e3dfaf,0,0,0,-1
+f207bb8bcccdc76143380849402a4f21,227.9078,263.1494,137,8.6697
+f243bd277f1876a77a0fb18f9092105a,0,0,0,-1
+f27d7bf8df3cf0cd187682fc6860b755,0,0,0,-1
+f2e952758095bc50691ab02f724568d2,300.0532,314.3494,104,5.9844
+f39a1e54d79731e4417aa8159d19b7d4,0,0,0,-1
+f39dacd5f134f3f4482094d3f8a0aff1,194.661,364.5519,130,9.974
+f3d40bbf94a7951dee3b0028e301a126,0,0,0,-1
+f44dd045f6dcb1e477e6d3dc0f29d7e8,0,0,0,-1
+f4bee414210374e68b6746f70b38d461,62.339,319.3364,54,11.9873
+f52bd66210db45189027991781e1162b,0,0,0,-1
+f55f99177e8b4b267c71b4e5fa4116be,0,0,0,-1
+f5630f467acd9aa977b61a3e5780c2eb,0,0,0,-1
+f5713e8c98ef5378ea678fb8d9192e13,0,0,0,-1
+f599c9bb0bd19126e13fba8b63d2de41,0,0,0,-1
+f69c80f898c9dfd8d3595b7ca7b8c66c,0,0,0,-1
+f6a2e171a3be579b564cd855985ab9d1,0,0,0,-1
+f6a9611b3afd5c6a5fb4a718cd2c38c2,0,0,0,-1
+f6bf2c352e3c5b13ae48f077570f3d15,0,0,0,-1
+f73624b8b22774acf9a3e2c748131eac,0,0,0,-1
+f74cbe4dda0f80dd66e15e64563689c6,73.9753,202.9727,66,10.7218
+f77fd9fd7966b346ce8e7efcb96c7c53,0,0,0,-1
+f78944bd1732001a3c62723a8cc19856,421.0714,279.1078,94,16.6765
+f79681d8561b6443a5b95f78f3ea6411,0,0,0,-1
+f7cdd95c94818875ece1175561025038,0,0,0,-1
+f82560aeea0309873716efe3aa71ef0a,0,0,0,-1
+f83c62177ee552891d22df33be12ab07,0,0,0,-1
+f88ed45f3436cb30e494409dae76df5d,403.7831,337.9545,42,19.9923
+f89a08a93f1ceaccb0cba52156fd6f03,0,0,0,-1
+f8ecf6be8ae631c6dd694c9638a02b45,128.1675,284.4273,96,31.3155
+f8ecf6be8ae631c6dd694c9638a02b45,127.5026,237.2169,91,8.6697
+f8ecf6be8ae631c6dd694c9638a02b45,121.1857,219.5961,88,12.0425
+f8ecf6be8ae631c6dd694c9638a02b45,124.3143,180.5143,86,9.4407
+f8ecf6be8ae631c6dd694c9638a02b45,153.4351,240.2091,87,8.9458
+f8ecf6be8ae631c6dd694c9638a02b45,179.3675,338.6195,76,17.3011
+f8ecf6be8ae631c6dd694c9638a02b45,139.8039,377.1857,63,58.3327
+f9ce0c5ded59a58b9d7ca5200e6b1182,0,0,0,-1
+fa744c0374ccc6aaf6711f463a9e5bc2,0,0,0,-1
+fa7bf17071e3234ab1f350341303b174,139.8462,161.9744,76,7.0467
+fa7bf17071e3234ab1f350341303b174,96.85,366.925,76,7.1365
+fa7bf17071e3234ab1f350341303b174,408.4377,363.887,78,5.3195
+fa7bf17071e3234ab1f350341303b174,343.6667,340.7857,70,7.3127
+fa7bf17071e3234ab1f350341303b174,346.5987,289.4143,42,5.3195
+fa9575f64e6881c6b2730f0e225c9573,0,0,0,-1
+fa968673987cfd078d91641294c3bf63,0,0,0,-1
+fac65dbf7b6972049cfd37b5b122ec0b,444.6175,266.5628,72,15.2644
+fb7ae70f05b6441ac4ea7187ce7c45f7,0,0,0,-1
+fb7dfb6aae597d97c2da24179df0fe56,0,0,0,-1
+fbaa8548e6c3753836579c7987d0034d,0,0,0,-1
+fbe0c3d6e4a50ca1c1bd3101515d0ab4,0,0,0,-2
+fc658f9bc12a751a17f16589f9e3619b,0,0,0,-1
+fcdc2d423356d53759a8f602d40785a6,0,0,0,-1
+fd4c2d4738bc25a5c331dbc101f3323a,0,0,0,-1
+fd64b23b8cd8c371c8f76fbb503e4e0e,0,0,0,-1
+fd7c0fb3c0e764357aa58e5f047be614,213.9442,208.6247,98,14.2302
+fdf2a2f5b86aea0da54732056fc7ab48,163.7416,357.5701,33,19.5563
+fdf73dcce35167f3ed952a58f5a6f738,117.6818,188.75,69,7.4848
+fe26fd2bb25112b3c2ca93eb8e34f8ed,0,0,0,-1
+fe5c37e82b412833b8ad0abb57978377,0,0,0,-1
+ff5d8e90500cf324e7b04a2f07cf0399,0,0,0,-1
+ffe02fe7d2223743f7fb455dfaff3842,0,0,0,-2
diff --git a/training/detector/labels/label_job5.csv b/training/detector/labels/label_job5.csv
new file mode 100644
index 0000000..b89bb0a
--- /dev/null
+++ b/training/detector/labels/label_job5.csv
@@ -0,0 +1,632 @@
+id,coordx1,coordx1,coordx1,diameter
+666becc9794c25bb8e0e7982be7cb6dc,0,0,0,-1
+799b283083f1b6547d558f063b318e78,0,0,0,-1
+79e7773230a96a6789c2c64ec39312cb,0,0,0,-1
+81affb342fc98aae0201a6c837cfc3bb,0,0,0,-1
+8264a875a465c029f28110c725fec283,360.2299,169.061,220,9.885
+e58cc57cab8a1738041b72b156fedc56,186.3494,125.5078,60,10.7424
+e58cc57cab8a1738041b72b156fedc56,116.8636,202.6403,53,32.3161
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
+,,,,
\ No newline at end of file
diff --git a/training/detector/labels/label_qualified.csv b/training/detector/labels/label_qualified.csv
new file mode 100644
index 0000000..7e21656
--- /dev/null
+++ b/training/detector/labels/label_qualified.csv
@@ -0,0 +1,481 @@
+id,coordx1,coordx2,coordx3,diameter,isMerged,isSpecial
+0015ceb851d7251b8f399e39779d1e7d,0,0,0,0,0,0
+006b96310a37b36cccb2ab48d10b49a3,0,0,0,0,0,0
+008464bb8521d09a42985dd8add3d0d2,102.7163,296.9362,110,13.3988,0,0
+00edff4f51a893d80dae2d42a7f45ad1,0,0,0,0,0,0
+0257df465d9e4150adef13303433ff1e,140.1664,368.7945,82,27.9374,0,0
+0257df465d9e4150adef13303433ff1e,173.1871,302.7938,87,37.4411,0,0
+02801e3bbcc6966cb115a962012c35df,98.5909,254.1364,169,5.2926,0,0
+028996723faa7840bb57f57e28275e4c,93.0561,280.715,124,16.5068,0,0
+04a8c47583142181728056310759dea1,0,0,0,0,0,0
+05609fdb8fa0895ac8a9be373144dac7,120.2647,244,83,6.5795,0,0
+05609fdb8fa0895ac8a9be373144dac7,141.2881,320.9492,54,8.6672,0,0
+059d8c14b2256a2ba4e38ac511700203,438.093,245.1066,50,25.6318,0,0
+059d8c14b2256a2ba4e38ac511700203,216.8115,321.1,108,25.731,0,0
+064366faa1a83fdcb18b2538f1717290,152.5961,391.5067,46,65.3738,0,0
+0708c00f6117ed977bbe1b462b56848c,355.9606,215.4853,126,8.3161,0,0
+07349deeea878c723317a1ce42cc7e58,93.6111,390.25,71,6.7703,0,0
+07bca4290a2530091ce1d5f200d9d526,138.241,331.6936,111,29.8982,0,0
+081f4a90f24ac33c14b61b97969b7f81,182.9869,343.2775,242,22.054,0,0
+081f4a90f24ac33c14b61b97969b7f81,123.956,308.8352,155,10.7641,0,0
+09d7c4a3e1076dcfcae2b0a563a28364,317.3385,400.0514,111,49.6006,0,0
+0acbebb8d463b4b9ca88cf38431aac69,160.8256,165.3605,130,10.4642,0,0
+0acbebb8d463b4b9ca88cf38431aac69,410.3051,349.8084,161,26.3865,0,0
+0c0de3749d4fe175b7a5098b060982a1,381.5948,326.9085,104,30.9125,0,0
+0c37613214faddf8701ca41e6d43f56e,236.6862,271.1596,125,15.4716,0,0
+0c60f4b87afcb3e2dfa65abbbf3ef2f9,120.8097,307.7684,111,23.2818,0,0
+0d06d764d3c07572074d468b4cff954f,144.76,372.36,161,5.6419,0,0
+0d06d764d3c07572074d468b4cff954f,353.375,328.3125,235,4.5135,0,0
+0d06d764d3c07572074d468b4cff954f,341.3,367.3,235,3.5682,0,0
+0d06d764d3c07572074d468b4cff954f,285.3571,392.7857,235,4.222,0,0
+0d06d764d3c07572074d468b4cff954f,382.3,323.3,225,3.5682,0,0
+0d06d764d3c07572074d468b4cff954f,160.22,398.44,191,7.9788,0,0
+0d06d764d3c07572074d468b4cff954f,131,307.5,247,4.5135,0,0
+0d06d764d3c07572074d468b4cff954f,141.3158,399.1579,173,4.9185,0,0
+0d06d764d3c07572074d468b4cff954f,125.3,353.7,238,3.5682,0,0
+0d06d764d3c07572074d468b4cff954f,115.8333,371.9333,174,6.1804,0,0
+0d06d764d3c07572074d468b4cff954f,187.1667,358.2619,127,7.3127,0,0
+0d06d764d3c07572074d468b4cff954f,339,308.1739,352,5.4115,0,0
+0f5ab1976a1b1ef1c2eb1d340b0ce9c4,0,0,0,0,0,0
+0ff552aa083ecfabaf1cfd65b0a8e674,106.1,207.38,102,7.9788,0,0
+0ff552aa083ecfabaf1cfd65b0a8e674,388.7849,301.4372,73,30.1934,0,0
+118be21b7e0c3058b29a524686391c66,368.6135,248.8127,65,17.8769,0,0
+11fe5426ef497bc490b9f1465f1fb25e,358.3725,432.3987,71,19.7386,0,1
+12e0e2036f61c8a52ee4471bf813c36a,184.3311,316.0404,104,30.7574,0,0
+13bb12b3b27d5a7b4b142503a1ae9e73,127.9873,396.2917,128,21.2019,0,0
+1427be78bcf4aba96c5054b697be9b5b,0,0,0,0,0,0
+149cc798827099f8bdb97cf702027305,150.2036,359.7203,98,31.5633,0,0
+14f713c1ef037f6c531cffdff0e5fb2c,229.4987,187.4586,97,18.5953,0,0
+14f713c1ef037f6c531cffdff0e5fb2c,114.8824,362.5294,100,8.0582,0,0
+14f713c1ef037f6c531cffdff0e5fb2c,374.875,339.6667,116,5.5279,0,0
+15aa585fb2d3018b295df8619f2d1cf7,135.1649,174.1288,74,60.3449,0,1
+169b5bde441e8aa3df2766e2e02cda08,334.644,318.874,156,31.4735,0,1
+184c61740244f4ce8fb985af9bb3d8e8,0,0,0,0,0,0
+184fa4ae2b7ae010625d89f10186f1c5,0,0,0,0,0,0
+185bc9d9fa3a58fea90778215c69d35b,363.48,291.3625,193,16.0022,0,0
+198d3ff4979a9a89f78ac4b4a0fe0638,0,0,0,0,0,0
+1dab3271160e1380c5a70a1e3ba40cb7,159.0643,328.9201,64,25.5572,0,0
+1e0f8048728717064645cb758eb89279,146.9273,219.4606,72,14.4943,0,0
+1f49f0c1d7feedcae9024d251797407c,205.5734,349.1248,46,16.9797,0,0
+1fb4887efd403cd9c0f6970fc8b679b5,414.4065,269.8298,281,10.4567,0,0
+229b8b785f880f61d8dad636c3dc2687,0,0,0,0,0,0
+2365e0afe6844e955f3d4c23a16dc1a9,189.1676,201.472,189,22.0129,0,0
+243e69389ae5738d3f89386b0efddbcd,205.3811,335.729,105,45.1069,0,0
+243e69389ae5738d3f89386b0efddbcd,185.3126,382.481,104,28.9666,0,0
+245fe0c86269602b0dab44c345b0b412,85.5558,303.1786,139,23.8833,0,0
+245fe0c86269602b0dab44c345b0b412,94.1637,331.0124,148,30.4244,0,0
+2488c5b32e837dc848fe6fe4b1bbb7cb,0,0,0,0,0,0
+2619ed1e4eca954af4dcbc4436ef8467,156.014,393.8992,124,56.8522,0,1
+2619ed1e4eca954af4dcbc4436ef8467,411.3304,288.2864,237,23.5711,0,1
+274a81c75d244187247789bd71de2b3a,345.8025,289.6624,173,19.9949,0,1
+281bb28a077ccfcd40ce4a543a5aea89,62.3638,167.2931,71,10.0929,0,0
+281bb28a077ccfcd40ce4a543a5aea89,112.1,108.7,83,6.1804,0,0
+281bb28a077ccfcd40ce4a543a5aea89,401.4565,273.471,111,18.746,0,0
+281bb28a077ccfcd40ce4a543a5aea89,181.6241,319.1348,112,13.3988,0,0
+28a9b77a9113ce491433d3ea47fa8fc9,214.5743,292.4356,108,16.0373,0,0
+28e29fe26140703e5bbe570f982bd112,345.7069,243.512,123,21.224,0,0
+2969c7ad0e550fee1f4a68fcb3bbb9e5,456.9437,273.1831,150,16.4682,0,0
+29d92a1e253cef2c7f34c6db26ce11e3,129.5,192.875,208,5.5279,0,0
+2a20e4a4e6411f72374fdffebabfc235,149.737,364.0069,64,19.1824,0,0
+2a2300103f80aadbfac57516d9a95365,0,0,0,0,0,0
+2b861ff187c8ff2977d988f3d8b08d87,318.7056,372.3665,105,15.6179,0,0
+2c06f5c66f3c79515b7712605dea4400,289.4444,348.8,105,7.5694,0,0
+2d5cd7c1ee9a74a1244ddd6b55ad0446,128.3291,312.8952,211,13.0597,0,0
+2d977650e6388d2c45825a77e94437a2,354.2517,411.3304,80,15.1316,0,0
+2e8bb42ed99b2bd1d9cd3ffaf5129e4c,113.974,252.7403,151,29.1063,0,0
+2e8bb42ed99b2bd1d9cd3ffaf5129e4c,376.468,257.5254,177,55.2177,0,0
+2ebb1e8f14802c33f0e4215a7545d70d,165.7787,386.291,142,17.6258,0,0
+2ed8eb4430bf40f5405495a5ec22a76d,178.7692,303.5934,117,10.7641,0,0
+2f154a687b94f7b59fec7048cbfb5354,206.9406,377.8351,88,18.0987,0,2
+2fc3d8ef26fc7aafad44d5034673dd4c,319.731,331.6936,67,60.9114,0,1
+303b4b8425389134997a38b975c205d3,357.548,322.0339,100,21.2303,0,0
+30b8aa7f5688cab5ff0964f34b715c4d,372.0247,364.5053,88,15.7816,0,0
+30b8aa7f5688cab5ff0964f34b715c4d,368.8219,436.7945,59,16.6985,0,0
+31136e50b7205e9184227f94cdea0090,331.01,352.2009,135,12.4741,0,0
+318bf8045b625b40825552420abfe1ef,162.8498,361.0874,122,18.6581,0,0
+31f35f920a472a1c3eacb565fe027923,196.0033,308.7937,137,13.4823,0,0
+31f35f920a472a1c3eacb565fe027923,412.3558,325.5414,73,10.6997,0,0
+31f35f920a472a1c3eacb565fe027923,147.8111,201.472,100,10.634,0,0
+322bf0acacba9650fa5656b9613c75c8,374.4172,182.3318,382,12.0937,0,0
+322bf0acacba9650fa5656b9613c75c8,83.213,290.3371,260,5.5112,0,0
+3252220375d82c3720d36d757bb17345,0,0,0,0,0,0
+3285ba0f447f3091c0c7c061b47c2f62,153.2797,388.7724,118,30.7078,0,0
+3285ba0f447f3091c0c7c061b47c2f62,120.1194,370.9254,104,13.0619,0,0
+3285ba0f447f3091c0c7c061b47c2f62,135.5067,380.2276,70,15.7816,0,0
+32cda856b7ec759fd3ebaa363c505e88,135.5067,384.6709,99,30.8899,0,0
+33dd6666d9f0338929ecce58bb7c4cc3,165.2423,381.5948,124,17.773,0,0
+33dd6666d9f0338929ecce58bb7c4cc3,383.6667,390.825,43,12.3608,0,0
+3457880b1a66030feb8adaed6da805af,200.4466,258.2089,419,11.9577,0,0
+348a53f500ada390ddd00cc47d310b2c,0,0,0,0,0,0
+34c0760406297a3c8fd5077fb7cd95b0,210.3585,365.1889,59,11.681,0,0
+352c23fe8a3d0640ea531a6bf223732c,446.7979,368.0638,24,10.94,0,0
+35b9a3e9871499893f76c8e6c648562c,206.9406,237.3598,124,25.7955,0,0
+375a52b012066845a2eeb5032a92fc6b,140.8095,296.2358,122,23.696,0,0
+380eb569a5750648434cc8ae8da4a0a9,307.5681,295.2394,111,16.4682,0,0
+383c27906392e9ce57f6ab5ef1cb6f62,177.0798,257.9096,93,15.4716,0,0
+385f1f49b0c20563177c36b7470f1c46,189.1676,297.1729,91,28.1598,0,0
+398208da1bcb6a88e11a7314065f13ff,0,0,0,0,0,0
+39ebb8121ea6faec0405a4e8db883b55,370.9993,237.3598,86,52.826,0,0
+3a5bbc2f1f5d6d76a48ba5300105d998,117.3919,243.8538,63,7.394,0,0
+3f6431400c2a07a46386dba3929da45d,0,0,0,0,0,0
+4001d754871a8da824b8444e32dc6e0f,224.3718,301.9579,89,52.9938,0,0
+40c95c9be0bd7c290534ce374c58bec9,353.7289,301.4023,110,20.8979,0,0
+437e42695e7ad0a1cb834e1b3e780516,149.8618,345.3652,121,43.0654,0,0
+43f2ef8f53e1aa03bfb6378d0c20a8ac,305.3758,324.516,436,15.0542,0,0
+44988c6efa451e8d496188cb30669d44,393.5574,258.8925,56,49.4686,0,0
+4521c94debf37a4dc9f3b70366a21640,325.8832,262.994,174,25.0697,0,0
+4521c94debf37a4dc9f3b70366a21640,161.1409,230.1822,73,25.985,0,0
+48e592418247393234dd658f9112c543,314.8447,321.4369,157,11.4518,0,0
+4a782bbc2608288a3ed05e511af6f8bb,0,0,0,0,0,0
+4af17bcb31669a9eab0b6ef8e22a8dcf,440.3825,265.3865,68,27.5559,0,0
+4baa552f3a11782f39e16b345d401fb8,0,0,0,0,0,0
+4cc8af2efef2f41bf70684be25276ce5,0,0,0,0,0,0
+4cd70a98baca46b116071b32788d3c2d,172.2075,349.6038,196,8.2147,0,0
+4cd70a98baca46b116071b32788d3c2d,192.5854,373.7336,177,27.5898,0,0
+4d7df08f074b221eec6311c2617a5ba8,349.8084,408.2543,81,26.0119,0,0
+4dbda61d574417c7f25d6e9a8f0749a7,223.0047,270.5134,108,15.8555,0,0
+4dbda61d574417c7f25d6e9a8f0749a7,325.1996,259.9179,100,24.1875,0,0
+4dcd34bd9b10f96453b63d4f55d1fd44,367.5814,375.7844,71,15.0542,0,0
+504e447ad62ea9ebb283873e044b5dd2,394.9246,244.8792,102,50.1394,0,0
+51bd5c556c77ecdaf489d8dd9f7a05f1,188.1422,358.0113,64,56.3112,0,0
+51fbac477a3639f983904fc4d42b8c15,197.7123,408.2543,99,15.7816,0,0
+51fbac477a3639f983904fc4d42b8c15,187.4586,403.4693,198,10.612,0,0
+5267ea7baf6332f29163064aecf6e443,376.468,268.8044,102,54.959,0,0
+54056288ab97cebc4b0ea33c23f47ff6,188.8258,378.5187,71,7.0379,0,0
+54056288ab97cebc4b0ea33c23f47ff6,91.7577,370.9993,57,6.1901,0,0
+5572cc61f851b0d10d6fec913ae722b9,386.0381,344.6816,90,20.5073,0,0
+5572cc61f851b0d10d6fec913ae722b9,144.0514,292.7296,133,42.7988,0,1
+55c01868f1d9c37fa3f174dc3c0d44e8,128.181,281.2095,130,11.5624,0,0
+55c01868f1d9c37fa3f174dc3c0d44e8,125.9366,241.1195,58,5.206,0,0
+56462ba8833fc842d16be7e311214404,323.3842,361.4237,100,26.0017,0,0
+56462ba8833fc842d16be7e311214404,36.0461,236.6762,33,8.2029,0,0
+570ea80b0dcc08f3e8751a6f4b2b1cd5,93.4666,324.516,28,17.891,0,0
+573a661e2d784f9385a3b78c9757ddad,331.01,228.8151,262,35.1362,0,0
+57822feb6186b788c4e1877123428454,404.0929,291.6831,124,15.2644,0,0
+57822feb6186b788c4e1877123428454,176.8632,348.783,80,26.1195,0,0
+5782e6873c666529c6a66421acb043dc,332.3772,284.8685,129,67.7605,0,0
+592c2481f17d6a2cecfe7bbb6a27722c,348.8723,338.5957,140,7.7358,0,0
+592c2481f17d6a2cecfe7bbb6a27722c,188.8258,357.3278,139,10.634,0,0
+592c2481f17d6a2cecfe7bbb6a27722c,417.1409,285.2103,114,10.612,0,0
+59fc9d939f05bf3023c1387c1c086520,142.0007,158.0648,44,13.6716,0,0
+59fc9d939f05bf3023c1387c1c086520,374.7368,253.4737,68,4.9185,0,0
+5ade88428e6463fa212d4c287228e8ed,201.8138,319.3892,201,9.2977,0,0
+5ade88428e6463fa212d4c287228e8ed,132.7724,238.0434,181,11.377,0,0
+5ade88428e6463fa212d4c287228e8ed,133.7977,383.6455,123,19.9061,0,0
+5b412509bc40a3aeb3b5efef1fdfcfc9,375.4426,278.7163,97,11.8004,0,0
+5b642ed9150bac6cbd58a46ed8349afc,0,0,0,0,0,0
+5e0c8cba8eab51076ac0014049d770c1,327.6481,205.3,91,85.2622,0,0
+5fd33ea74e1ad740a201ae9b3c383fc5,192.6662,244.5312,116,28.9686,0,0
+608202eb3c368512e55e9e339a203790,179.0351,293.7364,159,36.8844,0,0
+608a7028689c6ab3aea5f116007169b2,378.5156,261.1545,91,9.974,0,0
+60b389fb2f7eeb912586d1a3ccc9dbbc,0,0,0,0,0,0
+61630ec628631f7fe3980f869e1a4fbe,135.6293,333.3923,76,33.5112,0,0
+61630ec628631f7fe3980f869e1a4fbe,88.6949,288.8305,65,12.2573,0,0
+6171d57221e26d1f15d3c71fe966ab18,179.8421,185.7895,159,6.9558,0,0
+624a34fa8fd36847724e749877343847,122.8481,302.3805,91,17.9656,0,0
+627499714e279203bd1294290f8fc542,74.3078,354.2455,76,8.0344,0,0
+627836151c555187503dfe472fb15001,79.5758,257.6364,94,6.482,0,0
+627836151c555187503dfe472fb15001,427.8804,282.3152,87,10.823,0,0
+627836151c555187503dfe472fb15001,436.75,295.5,80,4.5135,0,0
+627836151c555187503dfe472fb15001,301.7156,146.1208,81,7.3444,0,0
+627836151c555187503dfe472fb15001,101.12,168.38,74,7.9788,0,0
+627836151c555187503dfe472fb15001,361.3333,336.125,62,5.5279,0,0
+627836151c555187503dfe472fb15001,117.5918,190.2245,53,7.8987,0,0
+627836151c555187503dfe472fb15001,175.8824,349.5588,61,6.5795,0,0
+63b5be42543c98ac5392f1bfbda085bf,0,0,0,0,0,0
+648c99653d512edc1d28dd8e7054ceab,361.2273,240.5416,291,27.1649,0,0
+64a5a866461a3b6006efb0075e04dffe,0,0,0,0,0,0
+65073aadb60e398d8db1806f5ea2a082,169.061,337.2896,119,22.9571,0,0
+65073aadb60e398d8db1806f5ea2a082,82.6195,152.4377,43,14.1367,0,0
+6541df84fd779ba6513a530c128f4e9b,0,0,0,0,0,0
+65a380c07d416f78e85545eaaa2916a1,317.3416,307.3675,216,16.1786,0,0
+65a380c07d416f78e85545eaaa2916a1,301.7156,294.4013,204,27.7844,0,0
+65a380c07d416f78e85545eaaa2916a1,401.1234,304.3753,173,19.6466,0,0
+662153a685fb4268361bfbaca5e9ca23,336.2922,342.9416,87,12.6513,0,0
+668bb968918c63fad7d65581825b1048,188.8718,358.9487,162,7.0467,0,0
+668bb968918c63fad7d65581825b1048,143.3913,386.4783,129,5.4115,0,0
+668bb968918c63fad7d65581825b1048,368.7957,259.6882,50,10.8817,0,0
+66a92d789e440d3dbef3c69d20e20694,340.3,304.3,109,6.1804,0,0
+66a92d789e440d3dbef3c69d20e20694,164.9316,331.8061,102,18.2992,0,0
+66a92d789e440d3dbef3c69d20e20694,325.7255,333.6667,50,13.9573,0,0
+676467220abd8e2104417c5213664ef9,105.7812,195.4888,52,24.9522,0,0
+678c5ec1360784e0fe797208069e0bbb,204.7563,362.1572,112,28.4566,0,0
+6799964c08ad5ce7740defcd3bd037a6,0,0,0,0,0,0
+6857c76be618bb0ddced5f4fecc1695f,77,180.5,126,5.2926,0,0
+6857c76be618bb0ddced5f4fecc1695f,144.7188,277.4238,125,35.9845,0,0
+6969c031ee0c34053faff3aac9dd2da7,0,0,0,0,0,0
+6be677ba1631174397b0c1e26a46af30,359.5649,269.7987,88,31.259,0,0
+d7aa27d839b1ecb03dbf011af4bcb092,355.1529,202.7786,106,26.916,0,0
+e709901da9ba15a95d4a29906edc01dd,381.4524,227.5476,78,16.0181,0,0
+a88c585e7d81744eec091a6f0600bd7b,129.8582,244.4032,86,39.9739,0,0
+e58b78dc31d80a50285816f4ecd661e3,147.1306,379.0092,66,33.3397,0,0
+e5cf847e616cc2fe94816ffa547d2614,83.9286,285.0714,88,24.4285,0,0
+e6b3e750c6c7a70ca512d77defcfe615,0,0,0,0,0,0
+ed0f3c1619b2becec76ba5df66e1ea56,118.0909,191.7478,101,31.5341,0,0
+ed0f3c1619b2becec76ba5df66e1ea56,115.6549,203.623,97,39.4126,0,0
+e54b574a7e7c650edc224cbdede9e675,170.1418,263.0142,251,13.3988,0,0
+e54b574a7e7c650edc224cbdede9e675,310.2143,355.1667,179,40.2586,0,0
+d2eecd9f13a6d474338045d0c91cffbd,142.2143,367.7381,226,20.1293,0,0
+d2eecd9f13a6d474338045d0c91cffbd,133.8333,329.6429,85,63.9001,0,0
+dbfbc12c7a943a2dc0e34bfd4a636bca,0,0,0,0,0,0
+d6d5ed3055d084a6abf0f97af3fe2ff0,314.7857,359.3571,68,39.3323,0,0
+d991b1760fb8705de655a1da068f7a6a,118.2143,365.4524,58,27.6079,0,0
+dc9854bcdcc71b690d9806438009001d,333.4256,177.8146,127,23.5883,0,0
+c610439ebef643c7fd4b30de8088bb55,164.9796,396.6422,43,30.5914,0,0
+c3e8db4f544e2d4ecb01c59551eb8ef0,425.6429,238.2143,116,17.5404,0,0
+c3e8db4f544e2d4ecb01c59551eb8ef0,420.6905,218.7857,114,36.6349,0,0
+a14e41eea93d7667a87d458d5cb28272,332.1576,234.7416,161,34.8156,0,0
+e572e978c2b50aca781e6302937e5b13,167.5603,230.6983,176,12.153,0,0
+afb37b10bd304fa2c7b70cfaf1f489ed,0,0,0,0,0,0
+e38789c5eabb3005bfb82a5298055ba0,86.4245,323.0288,24,13.3034,0,0
+e38789c5eabb3005bfb82a5298055ba0,303.7381,373.0714,71,10.8287,0,0
+e38789c5eabb3005bfb82a5298055ba0,347.1875,291.875,72,7.8176,0,0
+ac68eb0a3db3de247c26909db4c10569,318.9762,326.5952,96,34.8982,0,0
+da821546432756d377777d7f4c41ca2f,417.9685,190.1989,99,42.1899,0,0
+da821546432756d377777d7f4c41ca2f,135.7381,406.9762,57,69.3961,0,0
+d917c781760710015473eee9ce82e051,145.6429,234.0238,106,48.1871,0,2
+af4dfdda000c16c4cb77ea236cf1e524,143.8021,241.643,52,41.6737,0,0
+b8dc33b670bb078d10954345c3ffbb3a,216.881,332.6905,48,14.0074,0,0
+cb64ff663195832e0b66a9bb17891954,157.4238,187.3642,86,19.6091,0,0
+c5887c21bafb90eb8534e1a632ff2754,116.339,324.2288,184,12.2573,0,0
+c5887c21bafb90eb8534e1a632ff2754,94.4924,278.2045,180,12.9641,0,0
+c5887c21bafb90eb8534e1a632ff2754,85.0714,291.1667,175,14.4762,0,0
+c5887c21bafb90eb8534e1a632ff2754,106.2188,312.8281,178,9.027,0,0
+c5887c21bafb90eb8534e1a632ff2754,176.2917,345.9667,128,12.3608,0,0
+c5887c21bafb90eb8534e1a632ff2754,395.4304,322.9873,73,10.0293,0,0
+bc38f78d1194f57452f6bb5eed453137,396.6905,332.6905,41,106.2577,0,2
+be2be08151ef4d3aebd3ea4fcd5d364b,0,0,0,0,0,0
+a532c6f9405e6f3a4229ea6e04b0d975,178.0638,263.1619,112,32.8201,0,0
+c4c801ae039ba335fa32df7d84e4decb,0,0,0,0,0,0
+eb008af181f3791fdce2376cf4773733,102.5952,393.2619,65,162.1855,0,1
+e43afa905c8e279f818b2d5104f6762b,0,0,0,0,0,0
+c05acf3bd59f5570783138c01b737c3d,0,0,0,0,0,0
+fd0c2dfe0b0c58330675c3191cef0d5b,79.3571,291.1667,109,23.3098,0,0
+fb57fc6377fd37bb5d42756c2736586c,143.3287,245.2736,51,23.5342,0,0
+ac00af80df36484660203d5816d697aa,160.6106,310.2601,106,28.5906,0,0
+e8eb842ee04bbad407f85fe671f24d4f,183.1824,176.2948,88,28.9446,0,0
+b6578699374a9954b9a8a9e7da2603b1,141.8333,256.119,119,30.0542,0,0
+b022a1d30d62ef2c1f0902f1a047a845,372.6905,363.1667,76,37.2087,0,0
+b84c43bed6c51182d7536619b747343a,68.0249,226.3607,119,22.6239,0,0
+a76b682e74918492c1f2ca4c13c29885,0,0,0,0,0,0
+fa45178d023325b255a3d4fc3e96cb7d,83.6591,273.8409,51,7.4848,0,0
+fa45178d023325b255a3d4fc3e96cb7d,191.3548,332.1613,109,8.8849,0,0
+c3b05094939cc128a4593736f05eadec,149.4524,352.881,136,29.1123,0,0
+a162d204827e4e89a2e5ba81cc53247a,166.3585,338.0283,120,11.6174,0,0
+c67e799bcc1e2635eb9164f6e8cf75f3,70.1765,306.7059,119,9.3049,0,0
+c67e799bcc1e2635eb9164f6e8cf75f3,187.5476,374.2143,390,27.2587,0,0
+c67e799bcc1e2635eb9164f6e8cf75f3,109.4524,293.0714,430,40.0417,0,0
+b5de57869d863bdc1b84b0194e79a9d3,395.1667,316.3095,154,47.5382,0,1
+d92998a73d4654a442e6d6ba15bbb827,0,0,0,0,0,0
+f5717f7cbc08d8bd942cd4c1128e3339,141.3593,338.9891,75,47.136,0,0
+aea6f1621333074412b9a6acdcda31a9,342.5952,267.1667,108,33.8169,0,0
+e659f6517c4df17e86d4d87181396ea6,212.6905,324.3095,116,25.235,0,0
+eed4db0cb0576c274de569e98a56a270,0,0,0,0,0,0
+df015da931ad5312ee7b24b201b67478,165.0714,385.2619,114,24.3094,0,0
+c67de8fbbe1e58b464334f93a1dd0447,0,0,0,0,0,0
+f25c425c827b35fcbaa23f2ed671540b,396.3095,208.119,81,18.5379,0,0
+f25c425c827b35fcbaa23f2ed671540b,382.2143,209.2619,78,20.5855,0,0
+ebd601d40a18634b100c92e7db39f585,342.9762,173.4524,134,31.0143,0,1
+aa2747369e1a0c724bea611ea7e5ffcf,0,0,0,0,0,0
+d09e4124b97b22ef45692b62b4ca7f03,367.3313,190.7398,53,25.0287,0,0
+d09e4124b97b22ef45692b62b4ca7f03,91.3793,278.3908,77,14.8843,0,0
+f3f6f40ccb01276d722d52701cab1754,222.9762,355.1667,298,31,0,0
+ea7373271a2441b5864df2053c0f5c3e,191.7381,232.5,97,77.4487,0,0
+f8f66fca04d2e67eacd86ea154827a4c,382.9762,344.119,69,41.2415,0,0
+a19a122fe9a790576b57c6bd5cf9ff5c,335.2476,380.9825,95,30.7574,0,0
+e10c2b829c39d4a500c09caf04d461a1,328.119,242.7857,80,45.0105,0,0
+f3eafe72b1e9528116f3c430ab73a2ae,163.7713,362.5964,127,16.8503,0,0
+f3eafe72b1e9528116f3c430ab73a2ae,300.995,307.299,174,22.5111,0,1
+fb99a80cbb2f441bb90135bab5b029fe,0,0,0,0,0,0
+fc545aa2f58509dc6d81ef02130b6906,109.5,175,131,8.1369,0,0
+fc545aa2f58509dc6d81ef02130b6906,143.2018,235.4495,177,11.7806,0,0
+eaf753dc137e12fd06e96d27f3111043,106.6278,273.9917,92,21.4095,0,0
+eaf753dc137e12fd06e96d27f3111043,158.2143,286.2143,57,66.3251,0,0
+cf0a772e90a14d77d664ce9baedf0e5c,0,0,0,0,0,0
+ac3345a5a05655c6bcce7d0b226a0042,133.096,316.6215,115,15.0121,0,0
+a32e7fdbc0db97e35aabd7c931a582ea,0,0,0,0,0,0
+e56b9f25a47a42f4ae4085005c46109c,68.5556,223.5556,57,7.5694,0,0
+e2b7fe7fbb002029640c0e65e3051888,0,0,0,0,0,0
+cfbcb16fea277226d6771d8b1966397a,339.5476,328.881,180,49.3418,0,0
+f2f23b265b2a3b977cb81fe3193d7c2c,0,0,0,0,0,0
+fd2dd970bd3d91e5b26d7e57c03f70af,135.2337,273.5647,196,33.3397,0,0
+bbe21f027a1df4b07016b474b48d3f65,351.08,165.7267,56,13.8198,0,0
+f6c9e875d7adfe7add08f43528810f72,362.2988,240.9084,184,17.8769,0,0
+f6c9e875d7adfe7add08f43528810f72,85.4524,345.6429,109,40.8384,0,0
+f467795ce3b50a771085d79ae8d29ecc,320.119,295.7381,146,32.1448,0,0
+ac9c16f3f287f0e0b321fb518ac71c75,343.3571,253.0714,90,39.3323,0,0
+d7e5640b52c8e092ec277febc81478da,348.6905,382.2143,62,135.8201,0,0
+c1673993c070080c1d65aca6799c66f8,138.2917,216.9896,73,11.0558,0,0
+c1673993c070080c1d65aca6799c66f8,366.9762,216.5,92,15.1808,0,0
+e537c91cdfa97d20a39df7ef04a52570,140.6578,283.8128,103,15.4304,0,0
+d2b47d9034d38a410f00dabba9754d91,210.7857,347.5476,66,36.2926,0,0
+d2b47d9034d38a410f00dabba9754d91,389.0714,283.5476,34,21.0732,0,0
+cb94c3f894fc93c1ec0eb436c8564ed3,218.8288,334.9009,50,11.8882,0,0
+aa55708fcc8bf27b605bcd2fca0dc991,391.7381,349.8333,105,27.4709,0,0
+b158f44c31f4121c865c828ff79fc73d,240.7418,253.9296,97,16.4682,0,0
+a853993fd839a0ee61f2ca73c4e497a6,0,0,0,0,0,0
+f1a64fda219db48bcfb8ad3823ef9fc1,0,0,0,0,0,0
+cd104ad99d5b939b6bdd28b154e28085,182.5952,141.4524,66,31.4695,0,1
+cd104ad99d5b939b6bdd28b154e28085,183.7381,261.0714,58,52.7698,0,1
+df761dd787bfc439890740ccce934f36,105.9234,272.5404,90,17.2977,0,0
+a13d6c5f8f86d74e16c10cf9294bca31,172.6905,362.7857,44,39.7726,0,0
+e9ccf1ce85c39779fafb9ec703c71555,375.0682,334.4318,195,7.4848,0,0
+e00832e96709eb85f8e0e608ca02c2b5,316.3095,373.0714,90,24.0574,0,0
+b7045ebff6dbb0023087e0399d00b873,204.8317,327.5721,148,16.2737,0,0
+f76143416ee2c8e1251f45f108fed468,342.2143,252.6905,115,51.927,0,0
+c0f0eb84e70b19544943bed0ea6bd374,118.8807,270.4187,63,24.2273,0,0
+c0f0eb84e70b19544943bed0ea6bd374,203.5476,220.6905,50,41.4311,0,0
+c0f0eb84e70b19544943bed0ea6bd374,175.7381,277.4524,73,49.4065,0,0
+f17867cc3e579dc2fc6f0334bc43a91d,174.939,127.4695,126,14.4503,0,0
+9e98136d07b953c3362e0a132c8810b6,97.4182,234.5545,104,11.8345,0,0
+ad7e6fe9d036ed070df718f95b212a10,436.3095,239.7381,115,31.6901,0,0
+bb4b43d0dc4d9d2b61150df6556f6490,0,0,0,0,0,0
+c1ba619e3b49e0cb7798bd10465c2b29,0,0,0,0,0,0
+fbae4d04285789dfa32124c86586dd09,0,0,0,0,0,0
+b6d8dd834f2ff1ed7a5154e658460699,84.8312,370.487,59,14.0028,0,0
+cd10ceca9862ba0cc2ffd0ed8c9b055c,323.1522,331.6739,135,17.1127,0,2
+f7a03adba817f2a2249b9dee0586f4be,0,0,0,0,0,0
+fda187bfb1d6a2ecd4abd862c7f7f94c,62.5952,221.4524,83,47.2442,0,0
+f2ca85bb9ae82a3d79b9f321f727ac19,407.5152,318.9333,159,14.4943,0,0
+b17cb533d71d63d548ce47b48b34c23c,194.7857,245.8333,115,48.3914,0,0
+9f52323d216f89d300612cfac0122d8b,0,0,0,0,0,0
+af6d573b8c6804e14e3a7b07a376e593,457.2619,218.7857,84,21.8176,0,0
+e5c68cfa0f33540da3098800f0daae2c,0,0,0,0,0,0
+d81704ee56c124cc1434640918a3299c,374.5952,332.3095,146,51.9941,0,0
+adc3bbc63d40f8761c59be10f1e504c3,376.825,279.4812,317,14.273,0,0
+ac366a2168a4d04509693b7e5bcf3cce,75.1196,254.6277,57,21.6461,0,0
+b6687898fe385b68d5ae341419ef3fdd,117.0469,273.7266,205,12.7662,0,0
+c2e546795f1ea2bd7f89ab3b4d13e761,345.5132,362.4079,102,13.9116,0,0
+c2e546795f1ea2bd7f89ab3b4d13e761,341.3403,270.7914,142,49.3529,0,0
+bda661b08ad77afb79bd35664861cd62,126.9762,265.6429,90,73.2777,0,0
+f29d00ddf6d9846aa600c3f0edf5f952,355.1042,278.6718,55,18.1595,0,0
+f29d00ddf6d9846aa600c3f0edf5f952,182.2143,354.4048,208,29.9381,0,0
+f29d00ddf6d9846aa600c3f0edf5f952,118.5952,242.7857,66,29.4099,0,0
+f29d00ddf6d9846aa600c3f0edf5f952,146.4048,214.5952,71,24.7238,0,0
+f29d00ddf6d9846aa600c3f0edf5f952,98.4048,265.6429,59,19.7655,0,0
+a8e650f8494e894be06c9cee08702aa9,177.0857,289.5,98,13.3512,0,0
+a2d9e657a673798f9ebdfec1b361f93a,368.881,379.1667,44,40.2081,0,0
+ba71b330a16e8b4c852f9a8730ee33b9,137.0498,371.5,50,22.6239,0,0
+c2bdfb6ab5192656b397459648221918,189.8333,299.9286,21,10.2504,0,0
+fe45462987bacc32dbc7126119999392,370.4048,331.5476,116,32.3249,0,0
+ac57a379cfea05c07d9befe8b9359495,179.8714,388.7857,121,9.4407,0,0
+ac57a379cfea05c07d9befe8b9359495,350.9227,258.8069,223,17.224,0,0
+c020f5c28fc03aed3c125714f1c3cf2a,336.5,421.4524,200,61.0143,0,0
+c0625c79ef5b37e293b5753d20b00c89,357.8333,286.5952,55,37.1463,0,0
+d777a77cc7a2ec2f1eed68799cc9075c,131.5476,298.0238,101,49.029,0,0
+d7713d80767cfdaad5e3db537849d8d0,0,0,0,0,0,0
+e3423505ef6b43f03c5d7bde52a5a78c,118.5488,281.2952,84,37.8974,0,0
+b635cda3e75b4b7238c18c6a5f1858f6,0,0,0,0,0,0
+d9a2bea7df4a888313374beb142cf9c0,149.9848,334.1364,29,9.167,0,0
+a4dc34f2731b62f60c6c390a39fe11b2,176.5,302.5952,81,67.3457,0,1
+d244870d213a21efa86e86c951d8c9a2,436.6905,355.9286,78,77.4149,0,0
+ac4c6d832509d4cee3c7ac93a9227075,130.7857,348.3095,119,28.6399,0,0
+f42a0343e5b5154c6a184fc955d8f20f,174.5952,352.5,143,47.367,0,0
+f725f46908f16062fd12c141eb47c6a7,334.2062,384.3541,50,18.0893,0,0
+d8ed783494996f55a587270a212f7d5b,408.5221,286.9116,39,17.8055,0,0
+a784a51caee14229d46777f2a9770a5f,93.8333,210.0238,88,16.0724,0,0
+a784a51caee14229d46777f2a9770a5f,166.5952,209.2619,119,59.8859,0,0
+a70fd23bd8d535ffd42259cb91f4c5ca,98.7926,298.1646,76,33.606,0,0
+f63f2f63e2619012b4c798fd638c8b8a,0,0,0,0,0,0
+c8cfb917b0d619cb4e25f789db4641f8,340.6466,308.258,118,18.9823,0,0
+ed49b57854f5580658fb3510676e03dd,130.6316,256.4605,155,9.837,0,0
+b7ef0e864365220b8c8bfb153012d09a,396.3095,240.5,172,45.8727,0,0
+b8bb02d229361a623a4dc57aa0e5c485,147.792,250.312,76,21.851,0,0
+f938f9022abf7f1072fe9df79db7eccd,104.119,250.7857,78,57.3254,0,0
+b83ce5267f3fd41c7029b4e56724cd08,192.881,370.4048,51,70.4422,0,0
+6cb2908fd789700db727dd96526bc342,168.3243,257.8476,171.5,56.8102,1,0
+6cb2908fd789700db727dd96526bc342,132.0671,379.8871,155,20.687,1,0
+6cb2908fd789700db727dd96526bc342,110.2143,246.2143,172,61.4125,1,2
+6ee742b62985570a1f3a142eb7e49188,219.1667,292.4031,174.5,37.6446,1,0
+6f43af3f636f37b9695b58378f9265cc,120.7218,252.4061,96,52.5648,1,0
+6f43af3f636f37b9695b58378f9265cc,368.5429,326.1143,83,9.4407,1,0
+6f43af3f636f37b9695b58378f9265cc,143.3113,239.2878,104,29.4462,1,0
+6fd3af9174242c1b393fe4ba515e7a26,0,0,0,0,1,0
+713d8136c360ad0f37d6e53b61a7891b,162.3113,332.3546,129,46.6991,1,0
+71665cc6a7ee85268ca1da69c94bbaeb,137.8111,324.2469,163,16.5586,1,0
+721949894f5309ed4975a67419230a3c,0,0,0,0,1,0
+72fd04cf3099b148d9ad361efb988866,328.6589,324.4223,177,18.6268,1,0
+733205c5d0bbf19f5c761e0c023bf9a0,197.0299,365.7606,74,20.744,1,0
+7395f64fba89c2463a1b13c400adf876,0,0,0,0,1,0
+74b1b748971c474a8023f6406c54b18a,387.3575,279.1142,137,24.266,1,0
+74b1b748971c474a8023f6406c54b18a,350.9762,235.1667,146,20.4724,1,0
+75aef267ad112a21c870b7e2893aaf8a,319.326,394.2732,101.5,23.8382,1,0
+761aeadb65fb84c8d04978a75b2f684c,0,0,0,0,1,0
+763ce10dfdd4662f15de3f5931d5534b,152.8498,408.4203,64,18.8927,1,0
+77033e4c1591403d1b1255607a20a983,154.7318,266.6609,58,16.9622,1,0
+775c5f8043e72b2284b5885254566271,184.9017,339.5338,144,14.0027,1,0
+77d6f5203d46073369d7038b2d58e320,133.0714,269.0714,97,15.633,1,0
+7842c108866fccf9b1b56dca68fc355e,0,0,0,0,1,0
+78c0a0104c0428e260cbd9e50eb7eea6,90.2833,187.5313,66,26.8087,1,0
+7917af5df3fe5577f912c5168c6307e3,306.5537,291.1459,301,35.4263,1,0
+799c0026d66479f7447ed0df5955f051,135.4645,260.3303,165,97.6698,1,0
+799c0026d66479f7447ed0df5955f051,89.2826,228.4003,157,91.67,1,0
+79e0e507b1cd1d0c8107de4fd6b9e444,388.0914,198.1242,96,46.7519,1,0
+7bfba4540956c0b2c5b78b3623a4855d,338.7754,198.0308,300,63.0759,1,0
+7c2b72f9e0f5649c22902292febdc89f,0,0,0,0,1,0
+7d46ce019d79d13ee9ce8f18e010e71a,336.0394,335.6134,100.5,52.1334,1,0
+7fb1c8ffd78ca4b6869044251add36b4,390.4765,294.0544,120.5,26.5944,1,0
+80600d4a5fee7424d689ba7d0906d50f,403.8316,239.8351,130,50.1886,1,0
+817a99e1a60bcf4e37c904d73845ca50,0,0,0,0,1,0
+820dd342da11af3a062d1647b3736fdd,190.9762,309.0714,208,83.2187,1,1
+823b5f08ce145f837066d2e19dab10c1,86.7684,376.5831,80.5,51.2035,1,0
+823b5f08ce145f837066d2e19dab10c1,106.2069,418.0345,61,6.0765,1,0
+8298238a27be6111214a9bc711608181,327.6922,375.5184,131,13.2554,1,0
+8326bb56a429c54a744484423a9bd9b5,193.6483,315.7925,215,19.4243,1,0
+8369f716ca2d51c934e7f6d44cb156e9,166.1721,330.3583,110,46.4581,1,0
+839502f9ff68fd778b435255690f3061,122.7083,353.2099,111,19.7462,1,0
+839502f9ff68fd778b435255690f3061,156.8463,375.5615,77.5,16.6088,1,0
+84876a50f52476bcc2a63678257ae8b4,99.0386,253.9546,101,39.1561,1,2
+84a6c418d57bfc5214639012998356d4,204.3303,362.1242,114.5,15.6322,1,0
+85d59b470b927e825937ea3483571c6d,162.4324,291.9805,141,20.5709,1,0
+8601f5424bcf4cd8e7bc3d649e9995a2,356.365,348.0048,68,48.5297,1,1
+868b024d9fa388b7ddab12ec1c06af38,366.2143,287.7381,57,105.8856,1,1
+87cdb87db24528fdb8479220a1854b83,108.4758,416.7909,89.5,49.9972,1,0
+87cdf4626079509e5d6d3c3b6c8bfc2e,201.1199,401.8125,82.5,31.4954,1,0
+880980cc7e88c83b0fea84f078b849e3,414.8462,255.1603,102.5,22.0267,1,0
+880980cc7e88c83b0fea84f078b849e3,154.3544,200.8507,57.5,11.3451,1,0
+8815efa67adb15b2f8cfd49ec992f48e,170.9208,302.4878,472,21.8404,1,0
+882107a204c302e27628f85522baea49,0,0,0,0,1,0
+88523579f4e325351665753e903cfdf5,386.0923,258.7231,43,9.0973,1,0
+88523579f4e325351665753e903cfdf5,359.4583,297.9583,60,7.8176,1,0
+88ae66cd575c45ec5bb0f1578e2f1c49,146.0965,399.1701,83,42.1078,1,0
+8918c484841c5d0a532fe146e9da61bd,391.371,317.158,143.5,32.7938,1,0
+893fbc465b9d8a25569659a2bac154ef,339.1563,369.7364,114,71.4325,1,0
+898bd4c517fb9cf94c7d06dae56b0136,227.3974,241.4111,211,16.4742,1,0
+898bd4c517fb9cf94c7d06dae56b0136,216.9828,300.0321,216.5,15.1359,1,0
+898bd4c517fb9cf94c7d06dae56b0136,143.3123,326.6965,187,16.7629,1,0
+89bfbba58ee5cd0e346cdd6ffd3fa3a3,121.9073,296.9351,204,26.1022,1,0
+8a97ff581c17a49a3ef97144efde8a19,0,0,0,0,1,0
+8b6e16b4e1d1400452956578f8eb97c4,395.7208,398.8169,110.5,29.1168,1,0
+8c63c8ebd684911de92509a8a703d567,89.6429,261.4524,98,26.5794,1,1
+8e92c4db434da3b8d4e3cafce3f072fb,190.5952,302.2143,99,43.6685,1,1
+8ed68f2dbf103a4bc0fd8708d8c1ac93,0,0,0,0,1,0
+8ee6f423ff988d10f2bb383df98c1b2e,392.8741,303.6793,184,37.7918,1,0
+90409f7fcfec3581033559f8340e48a9,190.005,260.331,137.5,10.6746,1,0
+90e3b396e1c1343a514eb5890833d3d8,361.0807,295.8562,138.5,22.1399,1,0
+90e5f4780b2f05136ff5f776a5cbc2af,136.6078,236.4984,87,16.3117,1,0
+91d29bc19205f8eb9a63de5b774a5575,403.9722,251.7222,158,9.5746,1,0
+91d29bc19205f8eb9a63de5b774a5575,167.2387,298.048,200,10.9275,1,0
+91d29bc19205f8eb9a63de5b774a5575,135.9667,372.8948,113,43.6469,1,0
+91d29bc19205f8eb9a63de5b774a5575,390.4221,348.5242,110.5,32.1016,1,0
+92abfd85dd6afb639e9a8b60aaa08262,173.3693,346.4775,93,59.2349,1,0
+92abfd85dd6afb639e9a8b60aaa08262,162.2686,223.0329,82,30.7158,1,0
+9397a41c9e819a92eb5c86e0e652d7c1,0,0,0,0,1,0
+93a6f37a72f60498986374f57bfc30c4,169.2733,344.9682,363.5,15.1717,1,0
+95a27273c11db8bfb9fc27b1e64de6bd,0,0,0,0,1,0
+9660e4a23b8dd7d5056a622ee3568a41,98.0708,154.7229,92,14.9905,1,0
+9660e4a23b8dd7d5056a622ee3568a41,182.339,300.9675,56,39.8759,1,0
+96acca47671874c41de6023942e10c16,214.152,363.9078,149,23.6615,1,0
+9703fd051751879432975535663150da,208.6074,288.0775,129.5,51.7218,1,0
+9a3174ffe867f602ee82c512a01420ee,124.1018,261.7329,199,77.9873,1,0
+9b7524785a9bf40f0651deeb3b05b75f,0,0,0,0,1,0
+9c779a4e5e56c77131f8e99d5eacb766,172.4954,251.6689,43.5,96.7756,1,1
+9de4a1ebcdf1cfd8566ed1d9b63cbeb7,0,0,0,0,1,0
+9e5c2e760b94b8919691d344cfdbac7f,382.5725,252.1003,136.5,14.9035,1,0
+9e5c2e760b94b8919691d344cfdbac7f,155,304,134,5.1709,1,0
+9e5c2e760b94b8919691d344cfdbac7f,174.2143,326.2143,142,18.9253,1,1
+9e922147900b3984c9345bdda573e882,410.9416,244.4931,94,45.6744,1,0
+9e922147900b3984c9345bdda573e882,352.9038,411.0881,71,13.2769,1,0
+9e922147900b3984c9345bdda573e882,365.5494,95.5857,71,20.8794,1,0
+9e922147900b3984c9345bdda573e882,151.7619,218.9524,85,8.9562,1,0
+9e922147900b3984c9345bdda573e882,381.662,372.0986,97,9.5079,1,0
diff --git a/training/detector/labels/label_stage1.m b/training/detector/labels/label_stage1.m
new file mode 100644
index 0000000..e78d490
--- /dev/null
+++ b/training/detector/labels/label_stage1.m
@@ -0,0 +1,178 @@
+clear
+clc
+close all
+lungwindow = [-1900,1100];
+lumTrans = @(x) uint8((x-lungwindow(1))/(diff(lungwindow))*256);
+
+path = 'E:\Kaggle.Data\stage1';
+cases = dir(path);
+cases = {cases.name};
+cases = cases(3:end);
+ header = {'id', 'coordx1','coordx1','coordx1','diameter'};
+
+labelfile = 'label_job2.csv';
+if ~ exist(labelfile)
+
+ initial_label = header;
+ for i = 1:length(cases)
+ initial_label = [initial_label;{cases{i},'x','x','x','x'}];
+ end
+ cell2csv(labelfile,initial_label)
+ label_tabel = initial_label;
+else
+ label_tabel = csv2cell(labelfile,'fromfile');
+end
+
+label_tabel = label_tabel(2:end,:);
+fullnamelist = label_tabel(:,1);
+uniqueNameList = unique(fullnamelist, 'stable');
+% uniqueNameList = fullnamelist(ismember(fullnamelist, uniqueNameList));
+annos = label_tabel(:,2:end);
+for i = 1:size(fullnamelist)
+ if annos{i,1}=='x'
+ lineid = i;
+ name = fullnamelist{i};
+ id = find(strcmp(uniqueNameList,name));
+ break
+ end
+end
+
+
+for id = id:length(uniqueNameList)
+ name = uniqueNameList{id};
+ disp(name)
+ found = 0;
+ folder = [path,'/',name];
+% info = dicom_folder_info(folder);
+ im = dicomfolder(folder);
+ imint8 = lumTrans(im);
+ rgbim = repmat(imint8,[1,1,1,3]);
+
+ h1 = figure(1);
+ imshow3D(rgbim)
+
+ while 1
+
+ in = input('add_square(a), add_diameter(b), delete_last(d), or next(n):','s');
+ if in =='n'
+ if found==0
+ label_tabel(lineid,:) = {name,0,0,0,0};
+ lineid = lineid+1;
+ end
+ break
+ elseif in =='d'
+ found = found-1;
+ lineid = lineid-1;
+ if found ==0
+ label_tabel(lineid,:) = {name,'x','x','x','x'};
+
+ elseif found>0
+ label_tabel(lineid,:) = [];
+ else
+ disp('invalid delete')
+ end
+ if found>=0
+ rgbim=rgbim_back;
+ imshow3D(rgbim)
+ end
+ figure(1);
+ elseif strcmp(in,'a')||strcmp(in,'b')
+ if found==0
+ label_tabel(lineid,:) = [];
+ end
+ if strcmp(in,'a')
+ anno = label_rect(im);
+ elseif strcmp(in,'b')
+ anno = label_line();
+ end
+ found=found+1;
+ label_tabel= [label_tabel(1:lineid-1,:);{name,anno(1),anno(2),anno(3),anno(4)};label_tabel(lineid:end,:)];
+ lineid = lineid+1;
+ rgbim_back = rgbim;
+ rgbim = drawRect(rgbim,anno,1);
+ imshow3D(rgbim)
+ else
+ figure(1);
+ continue
+ end
+% disp(label_tabel(max([1, (lineid - 4)]):lineid,:))
+ end
+ fulltable = [header;label_tabel];
+ cell2csv(labelfile,fulltable)
+end
+
+function [anno] = label_line()
+h_obj=imline;
+pos = getPosition(h_obj);
+center = mean(pos,1);
+diameter = sqrt(sum(diff(pos).^2));
+
+h = gcf;
+strtmp = strsplit(h.Children(8).String,' ');
+id_layer = str2num(strtmp{2});
+
+anno = [center,id_layer,diameter];
+h_obj.delete()
+end
+
+function [anno] = label_rect(im)
+h = gcf;
+h_rect=imrect;
+label_pos = round(getPosition (h_rect));
+mask = createMask(h_rect);
+strtmp = strsplit(h.Children(8).String,' ');
+id_layer = str2num(strtmp{2});
+im_layer = squeeze( im(:,:,id_layer));
+patch = im_layer(label_pos(2):label_pos(2)+label_pos(4),label_pos(1):label_pos(1)+label_pos(3));
+bw = patch>-600;
+se = strel('disk',round(label_pos(3)/12));
+bw2 = imopen(bw,se);
+re = regionprops(bw2,'PixelIdxList','area','centroid');
+if isempty(re)
+ disp('wrong place')
+ h_rect.delete()
+ anno = label_rect(im);
+ return
+end
+areas = [re.Area];
+[bigarea,id_re] = max(areas);
+bw3 = bw2-bw2;
+bw3(re(id_re).PixelIdxList)=1;
+h2 = figure(2);
+imshow(bw3)
+pause(1)
+h2.delete();
+
+diameter = (bigarea/pi).^0.5*2;
+centroid = re(id_re).Centroid+label_pos(1:2);
+anno = [centroid,id_layer,diameter];
+h_rect.delete()
+end
+
+function rgbim = drawRect(rgbim,tmpannos,channel)
+n_annos = size(tmpannos,1);
+newim = squeeze(rgbim(:,:,:,channel));
+for i_annos = 1:n_annos
+ coord = tmpannos(i_annos,1:3);
+ diameter = tmpannos(i_annos,4);
+ layer = round(coord(3));
+ zspan = 2;
+ newimtmp = newim(:,:,layer-zspan:layer+zspan);
+ if diameter > 40
+ coeff = 1.5;
+ else
+ coeff= 2;
+ end
+ newimtmp = drawRectangleOnImg(round([coord(1:2)-diameter*coeff/2,diameter*coeff,diameter*coeff]),newimtmp);
+ newim(:,:,layer-zspan:layer+zspan) = newimtmp;
+end
+rgbim(:,:,:,channel)=newim;
+end
+function rgbI = drawRectangleOnImg (box,rgbI)
+x = box(2); y = box(1); w = box(4); h = box(3);
+rgbI(x:x+w,y,:) = 255;
+rgbI(x:x+w,y+h,:) = 255;
+rgbI(x,y:y+h,:) = 255;
+rgbI(x+w,y:y+h,:) = 255;
+end
+% dicom_folder_info
\ No newline at end of file
diff --git a/training/detector/labels/lunaqualified.csv b/training/detector/labels/lunaqualified.csv
new file mode 100644
index 0000000..a011524
--- /dev/null
+++ b/training/detector/labels/lunaqualified.csv
@@ -0,0 +1,478 @@
+5,-24.014,192.1,-391.08,8.1433
+5,2.4415,172.46,-405.49,18.545
+5,90.932,149.03,-426.54,18.209
+5,89.541,196.41,-515.07,16.381
+7,81.51,54.957,-150.35,10.362
+10,105.06,19.825,-91.247,21.09
+12,-124.83,127.25,-473.06,10.466
+14,-106.9,21.923,-126.92,9.7453
+16,2.2638,33.526,-170.64,7.1685
+17,-70.551,66.359,-160.94,6.6422
+19,-96.44,9.7362,-175.04,6.7538
+20,-57.087,74.259,1790.5,13.694
+21,-98.136,-72.868,-221.82,18.128
+22,-69.127,-80.567,-189.81,8.648
+26,46.189,48.403,-108.58,13.596
+28,-38.096,-106.71,-139.55,13.684
+31,-80.952,10.343,-28.399,9.4544
+34,47.671,37.643,-99.89,30.61
+34,-60.764,-66.435,-100.21,16.883
+35,42.296,56.152,-84.662,6.478
+35,99.375,23.947,-138.57,9.1046
+40,-127.53,-29.608,-253.7,8.2693
+40,93.139,-5.6526,-213.91,6.2098
+42,-34.497,-9.3119,-37.448,7.3606
+43,86.403,50.875,-81.387,12.734
+47,88.256,230.52,-623.3,9.0118
+47,55.714,190.76,-579.65,10.889
+49,-63.098,-56.555,-332.98,10.333
+49,-164.35,-136.66,-301.58,9.2206
+50,-68.621,-84.035,-160.52,6.3342
+51,-117.72,160.49,-688.29,15.343
+57,49.313,-63.215,-118.8,22.133
+60,-94.292,60.226,-261.21,14.198
+60,-54.618,59.352,-236.07,13.932
+65,-129.05,-12.239,-79.498,21.828
+68,-86.737,50.435,-156.61,9.2598
+68,78.94,15.801,-95.356,14.953
+68,-60.615,50.429,-95.987,6.7366
+74,59.114,-158.58,-118.04,6.7203
+75,-96.96,48.936,-68.038,16.978
+77,97.49,28.55,-160.53,8.8428
+78,33.833,88.412,-101.78,10.463
+78,-104.49,78.052,-208.33,56.865
+79,69.529,-24.415,-137.82,7.0358
+80,-99.859,37.434,-170.46,12.319
+80,-78.667,66.422,-168.87,13.025
+81,44.141,100.38,-139.84,6.1334
+90,-91.919,87.004,1453.8,14.44
+90,-59.723,84.839,1368.4,9.7696
+91,74.282,57.094,-122.28,6.7066
+93,-33.326,50.441,-253.8,11.345
+93,-57.186,78.725,-133.62,13.652
+94,-61.475,-140.37,-59.317,9.3264
+95,-119.43,-48.796,-223.6,12.035
+97,-84.047,-42.015,-146.81,7.0537
+97,-70.323,56.204,-82.479,7.8888
+97,-86.854,15.042,-72.327,9.2583
+98,-109.14,-124.56,-105.89,14.151
+101,-103.72,153.39,-465.85,11.14
+101,-80.446,183.94,-467.88,17.694
+102,88.825,-213.34,168.26,17.746
+102,57.179,-191.04,182.11,10.076
+105,53.277,66.297,-254.54,17.374
+107,-91.212,-159.22,-181.03,6.3107
+107,-62.943,-91.857,-154.36,11.686
+108,-108.13,-176.56,-192.96,8.6216
+114,97.376,-102.6,-156.34,11.232
+115,-108.03,59.544,-256.41,8.438
+118,-101.01,24.07,-108.76,11.629
+120,156.49,-149.4,-280.77,6.0496
+121,67.927,-24.895,-78.858,16.595
+122,37.069,-156.56,959.58,7.3034
+126,-76.87,-149.53,-127.54,18.793
+130,138.48,50.14,-311.36,16.185
+138,91.419,-21.567,-257.8,24.773
+139,84.438,41.64,-38.625,6.4562
+142,-89.669,34.299,-128.56,23.484
+144,58.513,75.794,-279.29,15.992
+146,-71.614,20.407,-22.784,17.347
+147,38.149,1.8027,-70.907,7.047
+148,-114.09,-229.05,-171.18,6.3463
+150,-50.505,124.85,-550.37,6.8671
+154,112.5,-43.727,-199.01,12.817
+154,104.39,-9.9725,-183.34,9.8437
+154,55.391,11.937,-63.155,13.736
+156,-83.567,69.861,-119.36,16.451
+157,-32.449,49.382,-60.319,24.282
+158,-57.439,131.23,-520.36,15.485
+161,-118.04,-3.2187,-165.58,6.4683
+167,-87.631,-25.153,-119.22,11.476
+168,-48.731,19.905,-97.42,7.7654
+170,-58.645,29.438,-78.844,8.742
+172,39.297,69.528,-210.55,9.76
+176,-105.42,250.82,-624.21,9.3591
+176,-53.409,239.45,-635.49,9.3763
+176,57.832,268.89,-646.46,8.1524
+176,36.176,271.41,-690.78,9.4211
+178,116.23,-173.58,-162.72,7.3181
+179,-25.829,-91.168,-200.19,9.5873
+180,17.295,-80.61,-181.42,9.5622
+183,-62.463,40.617,-418.83,21.256
+187,-89.508,-219.18,-204.12,6.9086
+188,100.62,64.757,-211.96,10.572
+188,-87.674,-12.694,-120.93,20.484
+190,38.161,-132.23,-198.8,8.8337
+190,97.9,-130.77,-156.65,12.565
+191,-27.958,53.79,-10.409,6.2506
+194,-51.89,97.114,-115.61,16.333
+197,-76.005,38.004,-242.56,6.4639
+199,72.287,76.9,-190.46,21.454
+199,23.491,-47.634,-172.28,8.7858
+199,-47.403,-30.171,-169.62,12.823
+206,-136.71,62.061,-99.277,18.385
+210,-51.044,75.2,-101.55,14.837
+210,-116.29,21.161,-124.62,10.888
+210,-111.19,-1.2645,-138.7,17.397
+210,73.775,37.278,-118.31,8.6483
+212,76.494,88.158,-193.16,19.044
+214,104.09,25.522,-140.17,16.043
+216,-43.912,-43.242,-141.7,9.1472
+216,-36.513,-65.215,-124.43,14.616
+219,71.122,103.58,-148.45,7.046
+219,49.946,39.217,-239.83,12.381
+219,72.371,83.674,-244.38,6.3371
+219,-35.369,83.725,-150.25,7.0258
+219,-41.69,-7.1446,-158.72,7.6707
+219,-33.076,103.02,-192.64,6.4507
+219,-53.332,96.459,-226.26,10.985
+223,-66.474,58.44,-109.36,25.873
+231,56.208,86.343,-115.87,23.351
+232,134.42,86.577,-762.59,7.4018
+233,-78.51,-162.58,-64.409,6.9296
+237,38.836,104.87,-72.041,6.4098
+241,77.436,22.217,-194.86,8.8758
+241,25.469,-15.969,-116.7,7.6153
+242,-82.491,31.001,-213.68,14.157
+242,-36.367,-41.895,-147.41,17.158
+243,-46.594,64.339,-149.79,24.782
+245,-103.49,-63.8,-222.22,7.3528
+246,-43.907,-74.65,-213.26,11.048
+249,-64.795,-35.557,-65.405,11.471
+249,108.24,-23.006,-75.132,9.3466
+249,-50.874,61.489,-138.68,7.8229
+250,94.635,-17.372,-204.4,17.753
+251,91.807,-228.15,-206.73,15.481
+253,-50.869,86.607,-145.77,9.7727
+256,-60.494,70.546,-58.675,8.7091
+257,-55.188,174.39,-405.73,10.938
+257,79.036,209.82,-465.06,6.3055
+260,-95.298,189.23,-500.44,7.7948
+263,-47.597,38.356,-259.52,6.705
+272,-47.715,-32.475,-77.44,7.1416
+274,-32.754,8.7772,-111.78,6.9752
+275,56.24,-92.29,-277.1,8.983
+278,-47.899,-10.225,-96.114,20.16
+279,-106.86,9.0482,-122.35,23.688
+283,92.366,18.315,-84.536,9.6421
+283,-85.442,-50.321,-177.47,6.3226
+286,59.257,-34.723,-134.84,13.136
+286,78.296,-16.929,-163.95,19.348
+286,64.43,70.386,-216.67,20.525
+290,-87.98,-170.44,-67.398,8.2605
+296,88.873,-97.927,-169.22,8.181
+296,66.313,-135.7,-42.758,8.824
+298,-109.18,70.159,-107.62,8.3918
+304,-82.989,8.8409,-85.892,8.6046
+305,-83.158,-21.679,-97.004,18.783
+310,-130.89,-160.5,851.78,13.161
+311,57.42,33.204,-61.85,13.82
+312,99.829,-146.12,-169.53,18.825
+317,-69.812,-69.682,-166.63,12.627
+317,75.713,12.583,-135.3,9.9007
+318,67.247,-122.55,-155.52,20.412
+319,138.64,-118.77,-60.254,7.7485
+322,98.19,37.786,-70.467,14.881
+322,-75.666,-51.486,-93.677,10.201
+326,33.618,-158.89,-129.44,16.023
+328,52,155.92,-554.11,8.7932
+328,47.055,170.39,-527.55,19.849
+328,-64.764,222.43,-520.04,10.073
+329,68.293,71.327,-224.24,9.0022
+332,54.578,137.28,-626.59,13.963
+333,115.37,-179.87,-281.63,10.638
+334,70.309,-48.697,-147.2,7.8624
+334,114.99,36.943,-143.63,7.8417
+335,-39.569,-71.945,-218.78,6.3647
+335,-64.999,-71.028,-185.12,7.2885
+338,96.276,-23.557,-107.37,7.4777
+338,72.191,33.773,-115.45,6.5695
+338,87.579,9.7838,-100.93,9.0882
+340,-31.098,222.31,-512.32,6.7734
+344,141.31,23.488,-242.68,6.376
+353,123.02,85.595,-215.18,12.135
+353,96.413,92.614,-224.12,7.8794
+353,127.59,44.77,-188.87,6.4364
+353,-7.5422,60.292,-240.95,6.0114
+353,-33.967,114.13,-195.07,7.748
+353,-49.514,-13.582,-136.21,8.2449
+353,66.146,36.398,-72.803,9.6986
+353,79.18,73.328,-167.73,6.1028
+354,-102.38,-96.395,-138.86,25.415
+355,118.32,20.247,-155.28,13.849
+357,-84.394,246.93,-508.19,23.572
+358,75.476,71.694,-97.732,7.39
+360,-64.401,7.8415,-75.952,10.722
+364,-55.528,245.44,-758.13,13.843
+365,75.633,111.26,-182.14,6.2795
+366,38.176,76.658,-217.88,13.205
+367,28.822,-67.503,-119.49,14.744
+367,86.343,-24.242,-116.26,6.5421
+368,-88.879,252.97,-542.21,9.5847
+369,-91.776,193.67,-636.67,15.673
+373,-20.261,66.589,-206.24,7.79
+374,-149.07,-156.37,-422.12,6.5873
+375,-79.513,120.48,-68.384,6.3137
+376,72.883,-1.2814,-56.52,17.526
+377,-87.393,181.75,-508.56,13.181
+378,103.49,19.024,-227.21,9.2864
+378,-31.017,-25.196,-196.29,6.2309
+380,-73.172,-55.926,-183.72,14.798
+380,-73.664,-215.81,-183.91,6.4894
+387,97.956,28.735,-133.41,12.167
+387,95.351,50.215,-139.27,12.076
+389,67.291,-2.5114,-97.674,7.9203
+395,-64.823,-60.709,-192.06,7.9851
+396,-103.07,-201.97,-199.26,7.8249
+400,64.682,32.102,-236.2,11.603
+405,-58.146,-55.41,-195.86,6.0064
+409,-50.061,84.283,-182,7.016
+409,-55.354,-21.739,-170.02,6.5678
+411,-67.893,66.626,-201.73,6.2327
+412,37.291,-153.93,-230.49,8.3617
+414,31.352,49.994,-93.09,9.9532
+415,-105.49,-195.79,-231.98,7.3403
+416,-112.3,97.358,-324.51,10.431
+417,36.101,56.747,-225.46,15.27
+417,88.047,82.068,-235.18,9.5143
+417,76.803,80.647,-206.02,8.2204
+417,45.57,34.24,-140.18,12.997
+417,62.562,73.24,-255.62,12.14
+419,74.066,-121.25,-208.58,6.4294
+422,-54.533,-122.34,-106.85,12.068
+432,-101.13,-66.598,-149.26,6.6052
+433,30.322,113.81,-401.13,12.657
+434,93.408,32.615,-183.93,6.4051
+438,67.02,2.846,-85.926,12.468
+439,61.15,65.368,-282.88,8.8158
+439,-82.51,75.767,-284.3,6.765
+439,78.145,84.694,-181.04,8.2797
+439,129.66,32.395,-174.18,11.37
+440,-108.27,-128.03,-247.69,7.0706
+441,145.05,33.853,-189.8,6.2422
+441,123.67,65.766,-210.81,10.831
+442,100,22.006,-147.08,8.8716
+442,127.21,44.798,-164.79,7.7243
+445,-82.014,-28.011,-153.91,10.062
+446,-83.903,-43.197,-275.31,14.813
+448,60.161,67.202,-97.951,19.576
+454,78.919,28.07,-30.648,6.1459
+456,-36.289,37.18,1549.3,12.316
+459,94.799,-131.05,-139.71,6.0735
+461,-115.35,-13.637,-174.06,12.986
+463,-14.233,54.112,-168.7,18.021
+463,-47.1,55.212,-132.72,13.806
+464,-42.793,-131.46,-226.18,12.652
+465,-92.274,49.159,-179.91,6.359
+466,63.27,77.363,-225.93,13.448
+468,-41.618,178.41,-381.25,19.31
+470,-29.123,48.557,-85.505,10.727
+472,-56.693,-71.398,-160.15,6.0241
+476,36.991,75.969,-211.92,7.9689
+476,-55.693,73.998,-147.35,14.678
+487,-85.254,-46.796,-180.66,6.8566
+488,-71.455,-176.25,241.81,7.9778
+488,-93.681,-176.03,213.21,23.934
+493,-12.416,-184.51,867.18,12.17
+495,-94.171,60.229,-185.15,7.6363
+497,-49.728,-19.986,-151.93,14.314
+497,-71.783,-64.17,-210.64,8.2222
+501,123.64,-5.0811,-262.46,20.389
+503,-36.644,-76.576,-155.61,15.283
+503,107.3,-1.6683,-189.2,20.036
+503,129.14,35.495,-229.66,22.135
+504,-45.805,59.892,-200.99,8.7667
+504,-88.564,20.209,-103.74,7.0767
+506,96.78,1.5657,-113.1,22.039
+507,-48.522,45.382,-90.224,22.881
+510,-72.804,223.43,-567.17,6.0317
+511,-29.741,-18.462,-134.25,17.989
+512,-48.066,-258.05,-250.54,8.4139
+512,-90.94,-230.22,-217.07,7.6638
+513,33.018,94.395,-251.8,8.3283
+517,-67.46,-247.74,-211.1,7.7442
+517,-97.691,-134.07,-187.09,6.69
+518,69.529,87.036,-149.19,10.825
+524,51.489,9.855,-86.835,14.861
+526,-73.966,-92.445,-238.65,7.186
+526,-52.545,-195.13,-180.13,8.4366
+526,-85.941,-169.27,-128.35,7.5956
+526,-73.195,-102.81,-166.83,6.1726
+526,106.69,-126.23,-246.31,22.78
+527,-72.123,7.7971,-217.03,6.8443
+529,110.14,-32.017,-241.1,6.0054
+531,-88.491,4.6908,-184.93,18.51
+533,101.06,-2.9096,-129.73,6.4178
+533,111.8,34.379,-156.34,6.8988
+533,54.867,83.421,-200.52,15.998
+538,-66.079,27.442,-61.404,6.8621
+539,-90.942,9.4226,-72.519,22.225
+543,102.24,65.328,-240.7,18.21
+543,22.536,34.721,-117.44,10.34
+543,67.827,85.38,-109.75,32.27
+545,-59.391,91.298,-217.32,18.999
+545,-65.435,68.629,-282.43,13.553
+545,80.326,58.999,-150.48,12.714
+545,92.707,19.698,-194.27,8.8097
+550,76.666,-163.87,-147.25,15.693
+556,-130.2,27.57,-210.27,9.5032
+557,120.78,26.8,-282.4,7.9035
+558,60.464,6.6847,-166.26,6.2753
+560,92.755,28.68,-68.422,14.011
+565,33.105,-63.116,-108.73,10.759
+566,-79.344,175,-675.27,9.5476
+569,-57.726,73.779,-147.42,11.802
+569,-72.581,3.1897,-124.79,7.7408
+571,118.89,9.5434,-223.39,22.305
+571,-32.576,-38.5,-195.9,9.6516
+572,-55.107,-92.467,-105.13,6.8214
+578,91.67,-140.49,1158,13.058
+578,91.67,-140.49,1158,13.058
+578,73.324,-154.08,1175,12.764
+582,-35.865,50.09,-54.978,11.73
+588,-61.935,226.79,-379.06,6.9729
+588,22.141,196.1,-367.36,9.2539
+595,101.25,15.809,-105.57,16.095
+595,117.15,-1.52,-208.73,21.677
+602,48.842,-79.993,-170.12,7.7471
+603,-44.746,15.745,-199.21,11.066
+605,108.35,17.664,-144.35,7.1993
+605,-96.744,37.574,-138.16,9.0084
+605,64.422,10.399,-97.913,6.1804
+605,-61.414,86.922,-68.295,8.7486
+606,-43.175,-70.665,-149.53,8.489
+607,-46.842,58.349,-64.068,8.365
+610,-89.42,230.47,-614.34,7.6
+612,-6.6072,22.559,-143.79,9.4849
+612,119.21,-11.433,-208.29,6.8534
+614,-96.159,50.987,-126.45,10.321
+614,-129.56,43.951,-164.99,10.418
+614,-54.403,81.76,-286.54,15.711
+615,68.056,43.703,-266.02,12.686
+618,-104.13,5.5618,-43.863,13.14
+627,-97.411,-44.656,-143.89,24.663
+629,-87.927,-49.534,-117,9.4439
+635,-20.724,-82.434,-163.52,9.9911
+636,74.133,-26.753,-252.66,10.039
+638,72.189,-14.469,-195.24,22.469
+638,74.728,30.758,-101.31,18.868
+642,97.837,55.509,-280.98,21.082
+645,-34.217,-258.21,-180.59,8.7141
+645,-89.744,-177.92,-171.97,11.052
+645,81.069,-250.94,-166.75,9.3302
+646,-87.612,-12.625,-163.86,9.8217
+652,92.332,0.47116,-196.17,11.408
+652,76.373,-58.715,-188.32,6.7624
+652,38.185,-70.857,-177.4,7.0132
+652,73.403,-79.171,-160.47,7.3828
+652,54.101,-74.662,-158.29,6.1625
+655,29.809,60.468,-278.37,6.9554
+655,36.08,-29.736,-89.481,23.043
+659,-52.419,-24.794,-176.16,16.829
+663,-37.951,-30.073,-111.61,7.7364
+664,-36.556,94.954,-231.09,8.2083
+670,-90.57,207.98,-397.63,12.571
+670,-105.17,139.33,-448.43,7.1789
+670,-113.01,127.66,-453.05,8.2446
+677,87.929,-5.6235,-78.695,10.261
+679,-78.231,21.392,-185.92,11.841
+683,108.14,-9.0283,-127.66,9.5669
+685,-59.558,9.1483,-95.453,16.635
+686,-68.66,-222.49,721.58,6.4707
+703,16.893,206.01,-53.009,11.476
+703,-86.933,218.23,-221.67,9.6932
+707,122.16,-197.25,-159.47,12.951
+708,82.98,225.31,-584.62,17.153
+709,-41.47,39.42,-171.62,7.1211
+717,-97.07,-23.312,-166.01,10.803
+717,-136.54,47.458,-191.64,7.8515
+718,-106.91,-134.47,-187.21,7.601
+719,-104.33,-130.46,-81.178,12.304
+723,52.95,21.623,230.69,11.175
+724,67.939,-29.646,-125.73,6.168
+727,89.715,72.842,-235.99,11.232
+735,-152.36,-22.286,-274.37,7.8858
+736,-103.13,-5.7747,-206.36,27.075
+736,32.961,35.982,-176.78,16.923
+738,98.897,104.19,-208.78,8.0856
+739,119.21,11.45,-165.04,26.837
+739,-37.902,55.028,-80.003,17.719
+740,48.683,-15.356,-80.569,22.782
+741,-111.2,37.526,-67.136,15.393
+744,60.775,74.124,-214.78,25.233
+744,-85.421,25.262,-220.83,9.7566
+744,-108.53,-38.825,-199.21,10.989
+746,100.45,-88.728,-171.24,7.8058
+748,123.6,-8.0373,-208.26,7.2838
+752,-28.412,68.094,-217.51,7.2341
+752,105.19,48.219,-129.56,6.1316
+755,59.331,-24.992,-197.04,8.7358
+757,-124.67,21.097,-169.6,6.7319
+760,112.24,-132.08,-179.22,10.127
+762,-31.908,27.181,-170.15,10.168
+762,65.997,108.89,-168.72,7.9188
+762,-126.46,46.472,-203.92,7.0235
+765,-22.966,32.462,-207.39,18.409
+766,-43.535,61.082,-176.67,12.554
+767,-39.57,112.66,-173.71,20.884
+767,-59.919,-50.478,-171.93,6.0099
+767,-12.147,80.919,-147.91,6.872
+767,79.176,56.236,-153.67,8.2223
+770,-96.404,43.841,-155.37,11.487
+772,-73.156,-61.941,-261.6,21.579
+773,-107.93,46.064,-143.15,21.88
+774,127.29,-151.03,-245.18,7.9259
+777,-96.281,53.449,-196.18,17.724
+778,-45.91,-9.4096,-306.95,20.116
+784,-23.139,22.157,-179.84,21.151
+786,-27.135,88.963,-193.55,6.9677
+789,105.98,-105.19,-207.06,21.343
+791,73.043,8.2188,-54.187,15.125
+797,-93.46,60.144,1523.5,7.6745
+804,114.04,-22.69,-161.17,20.911
+807,59.497,-6.6966,-135.92,14.168
+809,-65.365,197.65,-672.1,12.449
+810,56.393,67.68,-64.674,19.654
+812,71.956,105.22,-534.73,7.4785
+812,35.819,171.34,-470.2,8.7279
+813,-68.685,206.2,-685.87,17.156
+815,67.698,-135.42,-167.49,6.6724
+821,-71.666,-60.409,-135.73,13.051
+821,92.054,-11.909,-96.799,12.973
+822,-107.32,-96.37,-211.97,15.354
+823,98.702,160.55,-418.74,13.343
+826,-75.743,37.461,-158.69,17.232
+830,-66.693,97.045,-267.31,17.336
+835,-48.614,-4.9129,-81.285,8.3496
+835,45.606,-33.229,-141.75,12.033
+835,56.741,-38.923,-214.44,17.604
+835,42.189,76.001,-230.09,9.8834
+835,23.623,78.542,-240.77,11.884
+835,17.205,8.9386,-256.56,8.119
+840,-47.537,-35.797,-137.33,13.642
+842,49.353,119.84,-209.7,6.9435
+843,-85.603,29.067,-107.85,7.2964
+845,-56.878,169.46,960.35,9.4964
+846,132.72,16.665,-130.31,10.438
+846,83.223,36.045,-47.98,16.945
+851,59.088,14.434,-83.776,17.411
+854,-106.77,143.13,-711.11,15.131
+857,109.12,48.59,-120.89,21.583
+858,-59.562,-21.608,-184.87,6.0965
+859,68.244,83.941,-296.89,7.0686
+859,-113.69,61.068,-204.51,6.6779
+859,30.716,-22.257,-151.4,14.221
+859,16.203,-28.689,-142.81,8.8462
+865,64.134,71.916,-126.18,8.5013
+865,-74.892,64.177,-112.4,6.2675
+868,-46.95,72.636,-95.645,27.442
+869,40.315,-80.724,-149.99,8.6871
+870,121.91,-67.416,-158.8,9.0616
+871,-84.152,21.816,-184.79,18.98
+871,-42.465,-36.855,-123.88,19.927
+872,-48.062,-65.097,222.29,6.5296
+873,87.077,222.25,-465.36,12.116
+873,55.973,250.6,-517.77,6.3195
+876,35.106,-25.062,-90.501,8.6206
+876,56.351,52.952,-83.782,14.915
+887,-21.958,33.486,-155.29,23.803
diff --git a/training/detector/labels/shorter.csv b/training/detector/labels/shorter.csv
new file mode 100644
index 0000000..b3f2e8f
--- /dev/null
+++ b/training/detector/labels/shorter.csv
@@ -0,0 +1,888 @@
+000,1.3.6.1.4.1.14519.5.2.1.6279.6001.100225287222365663678666836860
+001,1.3.6.1.4.1.14519.5.2.1.6279.6001.100332161840553388986847034053
+002,1.3.6.1.4.1.14519.5.2.1.6279.6001.100398138793540579077826395208
+003,1.3.6.1.4.1.14519.5.2.1.6279.6001.100530488926682752765845212286
+004,1.3.6.1.4.1.14519.5.2.1.6279.6001.100620385482151095585000946543
+005,1.3.6.1.4.1.14519.5.2.1.6279.6001.100621383016233746780170740405
+006,1.3.6.1.4.1.14519.5.2.1.6279.6001.100684836163890911914061745866
+007,1.3.6.1.4.1.14519.5.2.1.6279.6001.100953483028192176989979435275
+008,1.3.6.1.4.1.14519.5.2.1.6279.6001.101228986346984399347858840086
+009,1.3.6.1.4.1.14519.5.2.1.6279.6001.102133688497886810253331438797
+010,1.3.6.1.4.1.14519.5.2.1.6279.6001.102681962408431413578140925249
+011,1.3.6.1.4.1.14519.5.2.1.6279.6001.103115201714075993579787468219
+012,1.3.6.1.4.1.14519.5.2.1.6279.6001.104562737760173137525888934217
+013,1.3.6.1.4.1.14519.5.2.1.6279.6001.104780906131535625872840889059
+014,1.3.6.1.4.1.14519.5.2.1.6279.6001.105495028985881418176186711228
+015,1.3.6.1.4.1.14519.5.2.1.6279.6001.105756658031515062000744821260
+016,1.3.6.1.4.1.14519.5.2.1.6279.6001.106164978370116976238911317774
+017,1.3.6.1.4.1.14519.5.2.1.6279.6001.106379658920626694402549886949
+018,1.3.6.1.4.1.14519.5.2.1.6279.6001.106419850406056634877579573537
+019,1.3.6.1.4.1.14519.5.2.1.6279.6001.106630482085576298661469304872
+020,1.3.6.1.4.1.14519.5.2.1.6279.6001.106719103982792863757268101375
+021,1.3.6.1.4.1.14519.5.2.1.6279.6001.107109359065300889765026303943
+022,1.3.6.1.4.1.14519.5.2.1.6279.6001.107351566259572521472765997306
+023,1.3.6.1.4.1.14519.5.2.1.6279.6001.108193664222196923321844991231
+024,1.3.6.1.4.1.14519.5.2.1.6279.6001.108197895896446896160048741492
+025,1.3.6.1.4.1.14519.5.2.1.6279.6001.108231420525711026834210228428
+026,1.3.6.1.4.1.14519.5.2.1.6279.6001.109002525524522225658609808059
+027,1.3.6.1.4.1.14519.5.2.1.6279.6001.109882169963817627559804568094
+028,1.3.6.1.4.1.14519.5.2.1.6279.6001.110678335949765929063942738609
+029,1.3.6.1.4.1.14519.5.2.1.6279.6001.111017101339429664883879536171
+030,1.3.6.1.4.1.14519.5.2.1.6279.6001.111172165674661221381920536987
+031,1.3.6.1.4.1.14519.5.2.1.6279.6001.111258527162678142285870245028
+032,1.3.6.1.4.1.14519.5.2.1.6279.6001.111496024928645603833332252962
+033,1.3.6.1.4.1.14519.5.2.1.6279.6001.111780708132595903430640048766
+034,1.3.6.1.4.1.14519.5.2.1.6279.6001.112740418331256326754121315800
+035,1.3.6.1.4.1.14519.5.2.1.6279.6001.112767175295249119452142211437
+036,1.3.6.1.4.1.14519.5.2.1.6279.6001.113586291551175790743673929831
+037,1.3.6.1.4.1.14519.5.2.1.6279.6001.113679818447732724990336702075
+038,1.3.6.1.4.1.14519.5.2.1.6279.6001.113697708991260454310623082679
+039,1.3.6.1.4.1.14519.5.2.1.6279.6001.114195693932194925962391697338
+040,1.3.6.1.4.1.14519.5.2.1.6279.6001.114218724025049818743426522343
+041,1.3.6.1.4.1.14519.5.2.1.6279.6001.114249388265341701207347458535
+042,1.3.6.1.4.1.14519.5.2.1.6279.6001.114914167428485563471327801935
+043,1.3.6.1.4.1.14519.5.2.1.6279.6001.115386642382564804180764325545
+044,1.3.6.1.4.1.14519.5.2.1.6279.6001.116097642684124305074876564522
+045,1.3.6.1.4.1.14519.5.2.1.6279.6001.116492508532884962903000261147
+046,1.3.6.1.4.1.14519.5.2.1.6279.6001.116703382344406837243058680403
+047,1.3.6.1.4.1.14519.5.2.1.6279.6001.117040183261056772902616195387
+048,1.3.6.1.4.1.14519.5.2.1.6279.6001.117383608379722740629083782428
+049,1.3.6.1.4.1.14519.5.2.1.6279.6001.118140393257625250121502185026
+050,1.3.6.1.4.1.14519.5.2.1.6279.6001.119209873306155771318545953948
+051,1.3.6.1.4.1.14519.5.2.1.6279.6001.119304665257760307862874140576
+052,1.3.6.1.4.1.14519.5.2.1.6279.6001.119515474430718803379832249911
+053,1.3.6.1.4.1.14519.5.2.1.6279.6001.119806527488108718706404165837
+054,1.3.6.1.4.1.14519.5.2.1.6279.6001.120196332569034738680965284519
+055,1.3.6.1.4.1.14519.5.2.1.6279.6001.120842785645314664964010792308
+056,1.3.6.1.4.1.14519.5.2.1.6279.6001.121108220866971173712229588402
+057,1.3.6.1.4.1.14519.5.2.1.6279.6001.121391737347333465796214915391
+058,1.3.6.1.4.1.14519.5.2.1.6279.6001.121805476976020513950614465787
+059,1.3.6.1.4.1.14519.5.2.1.6279.6001.121824995088859376862458155637
+060,1.3.6.1.4.1.14519.5.2.1.6279.6001.121993590721161347818774929286
+061,1.3.6.1.4.1.14519.5.2.1.6279.6001.122621219961396951727742490470
+062,1.3.6.1.4.1.14519.5.2.1.6279.6001.122763913896761494371822656720
+063,1.3.6.1.4.1.14519.5.2.1.6279.6001.122914038048856168343065566972
+064,1.3.6.1.4.1.14519.5.2.1.6279.6001.123654356399290048011621921476
+065,1.3.6.1.4.1.14519.5.2.1.6279.6001.123697637451437522065941162930
+066,1.3.6.1.4.1.14519.5.2.1.6279.6001.124154461048929153767743874565
+067,1.3.6.1.4.1.14519.5.2.1.6279.6001.124656777236468248920498636247
+068,1.3.6.1.4.1.14519.5.2.1.6279.6001.124663713663969377020085460568
+069,1.3.6.1.4.1.14519.5.2.1.6279.6001.124822907934319930841506266464
+070,1.3.6.1.4.1.14519.5.2.1.6279.6001.125067060506283419853742462394
+071,1.3.6.1.4.1.14519.5.2.1.6279.6001.125124219978170516876304987559
+072,1.3.6.1.4.1.14519.5.2.1.6279.6001.125356649712550043958727288500
+073,1.3.6.1.4.1.14519.5.2.1.6279.6001.126121460017257137098781143514
+074,1.3.6.1.4.1.14519.5.2.1.6279.6001.126264578931778258890371755354
+075,1.3.6.1.4.1.14519.5.2.1.6279.6001.126631670596873065041988320084
+076,1.3.6.1.4.1.14519.5.2.1.6279.6001.126704785377921920210612476953
+077,1.3.6.1.4.1.14519.5.2.1.6279.6001.127965161564033605177803085629
+078,1.3.6.1.4.1.14519.5.2.1.6279.6001.128023902651233986592378348912
+079,1.3.6.1.4.1.14519.5.2.1.6279.6001.128059192202504367870633619224
+080,1.3.6.1.4.1.14519.5.2.1.6279.6001.128881800399702510818644205032
+081,1.3.6.1.4.1.14519.5.2.1.6279.6001.129007566048223160327836686225
+082,1.3.6.1.4.1.14519.5.2.1.6279.6001.129055977637338639741695800950
+083,1.3.6.1.4.1.14519.5.2.1.6279.6001.129567032250534530765928856531
+084,1.3.6.1.4.1.14519.5.2.1.6279.6001.129650136453746261130135157590
+085,1.3.6.1.4.1.14519.5.2.1.6279.6001.129982010889624423230394257528
+086,1.3.6.1.4.1.14519.5.2.1.6279.6001.130036599816889919308975074972
+087,1.3.6.1.4.1.14519.5.2.1.6279.6001.130438550890816550994739120843
+088,1.3.6.1.4.1.14519.5.2.1.6279.6001.130765375502800983459674173881
+089,1.3.6.1.4.1.14519.5.2.1.6279.6001.131150737314367975651717513386
+090,1.3.6.1.4.1.14519.5.2.1.6279.6001.131939324905446238286154504249
+091,1.3.6.1.4.1.14519.5.2.1.6279.6001.132817748896065918417924920957
+092,1.3.6.1.4.1.14519.5.2.1.6279.6001.133132722052053001903031735878
+093,1.3.6.1.4.1.14519.5.2.1.6279.6001.133378195429627807109985347209
+094,1.3.6.1.4.1.14519.5.2.1.6279.6001.134370886216012873213579659366
+095,1.3.6.1.4.1.14519.5.2.1.6279.6001.134519406153127654901640638633
+096,1.3.6.1.4.1.14519.5.2.1.6279.6001.134638281277099121660656324702
+097,1.3.6.1.4.1.14519.5.2.1.6279.6001.134996872583497382954024478441
+098,1.3.6.1.4.1.14519.5.2.1.6279.6001.135657246677982059395844827629
+099,1.3.6.1.4.1.14519.5.2.1.6279.6001.136830368929967292376608088362
+100,1.3.6.1.4.1.14519.5.2.1.6279.6001.137375498893536422914241295628
+101,1.3.6.1.4.1.14519.5.2.1.6279.6001.137763212752154081977261297097
+102,1.3.6.1.4.1.14519.5.2.1.6279.6001.137773550852881583165286615668
+103,1.3.6.1.4.1.14519.5.2.1.6279.6001.138080888843357047811238713686
+104,1.3.6.1.4.1.14519.5.2.1.6279.6001.138674679709964033277400089532
+105,1.3.6.1.4.1.14519.5.2.1.6279.6001.138813197521718693188313387015
+106,1.3.6.1.4.1.14519.5.2.1.6279.6001.138894439026794145866157853158
+107,1.3.6.1.4.1.14519.5.2.1.6279.6001.138904664700896606480369521124
+108,1.3.6.1.4.1.14519.5.2.1.6279.6001.139258777898746693365877042411
+109,1.3.6.1.4.1.14519.5.2.1.6279.6001.139444426690868429919252698606
+110,1.3.6.1.4.1.14519.5.2.1.6279.6001.139577698050713461261415990027
+111,1.3.6.1.4.1.14519.5.2.1.6279.6001.139595277234735528205899724196
+112,1.3.6.1.4.1.14519.5.2.1.6279.6001.139713436241461669335487719526
+113,1.3.6.1.4.1.14519.5.2.1.6279.6001.139889514693390832525232698200
+114,1.3.6.1.4.1.14519.5.2.1.6279.6001.140239815496047437552471323962
+115,1.3.6.1.4.1.14519.5.2.1.6279.6001.140253591510022414496468423138
+116,1.3.6.1.4.1.14519.5.2.1.6279.6001.140527383975300992150799777603
+117,1.3.6.1.4.1.14519.5.2.1.6279.6001.141069661700670042960678408762
+118,1.3.6.1.4.1.14519.5.2.1.6279.6001.141149610914910880857802344415
+119,1.3.6.1.4.1.14519.5.2.1.6279.6001.141345499716190654505508410197
+120,1.3.6.1.4.1.14519.5.2.1.6279.6001.141430002307216644912805017227
+121,1.3.6.1.4.1.14519.5.2.1.6279.6001.141511313712034597336182402384
+122,1.3.6.1.4.1.14519.5.2.1.6279.6001.142154819868944114554521645782
+123,1.3.6.1.4.1.14519.5.2.1.6279.6001.142485715518010940961688015191
+124,1.3.6.1.4.1.14519.5.2.1.6279.6001.143410010885830403003179808334
+125,1.3.6.1.4.1.14519.5.2.1.6279.6001.143412474064515942785157561636
+126,1.3.6.1.4.1.14519.5.2.1.6279.6001.143622857676008763729469324839
+127,1.3.6.1.4.1.14519.5.2.1.6279.6001.143782059748737055784173697516
+128,1.3.6.1.4.1.14519.5.2.1.6279.6001.143813757344903170810482790787
+129,1.3.6.1.4.1.14519.5.2.1.6279.6001.144438612068946916340281098509
+130,1.3.6.1.4.1.14519.5.2.1.6279.6001.144883090372691745980459537053
+131,1.3.6.1.4.1.14519.5.2.1.6279.6001.144943344795414353192059796098
+132,1.3.6.1.4.1.14519.5.2.1.6279.6001.145283812746259413053188838096
+133,1.3.6.1.4.1.14519.5.2.1.6279.6001.145474881373882284343459153872
+134,1.3.6.1.4.1.14519.5.2.1.6279.6001.145510611155363050427743946446
+135,1.3.6.1.4.1.14519.5.2.1.6279.6001.145759169833745025756371695397
+136,1.3.6.1.4.1.14519.5.2.1.6279.6001.146429221666426688999739595820
+137,1.3.6.1.4.1.14519.5.2.1.6279.6001.146603910507557786636779705509
+138,1.3.6.1.4.1.14519.5.2.1.6279.6001.146987333806092287055399155268
+139,1.3.6.1.4.1.14519.5.2.1.6279.6001.147250707071097813243473865421
+140,1.3.6.1.4.1.14519.5.2.1.6279.6001.147325126373007278009743173696
+141,1.3.6.1.4.1.14519.5.2.1.6279.6001.148229375703208214308676934766
+142,1.3.6.1.4.1.14519.5.2.1.6279.6001.148447286464082095534651426689
+143,1.3.6.1.4.1.14519.5.2.1.6279.6001.148935306123327835217659769212
+144,1.3.6.1.4.1.14519.5.2.1.6279.6001.149041668385192796520281592139
+145,1.3.6.1.4.1.14519.5.2.1.6279.6001.149463915556499304732434215056
+146,1.3.6.1.4.1.14519.5.2.1.6279.6001.149893110752986700464921264055
+147,1.3.6.1.4.1.14519.5.2.1.6279.6001.150097650621090951325113116280
+148,1.3.6.1.4.1.14519.5.2.1.6279.6001.150684298696437181894923266019
+149,1.3.6.1.4.1.14519.5.2.1.6279.6001.151669338315069779994664893123
+150,1.3.6.1.4.1.14519.5.2.1.6279.6001.151764021165118974848436095034
+151,1.3.6.1.4.1.14519.5.2.1.6279.6001.152684536713461901635595118048
+152,1.3.6.1.4.1.14519.5.2.1.6279.6001.152706273988004688708784163325
+153,1.3.6.1.4.1.14519.5.2.1.6279.6001.153181766344026020914478182395
+154,1.3.6.1.4.1.14519.5.2.1.6279.6001.153536305742006952753134773630
+155,1.3.6.1.4.1.14519.5.2.1.6279.6001.153646219551578201092527860224
+156,1.3.6.1.4.1.14519.5.2.1.6279.6001.153732973534937692357111055819
+157,1.3.6.1.4.1.14519.5.2.1.6279.6001.153985109349433321657655488650
+158,1.3.6.1.4.1.14519.5.2.1.6279.6001.154677396354641150280013275227
+159,1.3.6.1.4.1.14519.5.2.1.6279.6001.154703816225841204080664115280
+160,1.3.6.1.4.1.14519.5.2.1.6279.6001.154837327827713479309898027966
+161,1.3.6.1.4.1.14519.5.2.1.6279.6001.156016499715048493339281864474
+162,1.3.6.1.4.1.14519.5.2.1.6279.6001.156322145453198768801776721493
+163,1.3.6.1.4.1.14519.5.2.1.6279.6001.156579001330474859527530187095
+164,1.3.6.1.4.1.14519.5.2.1.6279.6001.156821379677057223126714881626
+165,1.3.6.1.4.1.14519.5.2.1.6279.6001.159521777966998275980367008904
+166,1.3.6.1.4.1.14519.5.2.1.6279.6001.159665703190517688573100822213
+167,1.3.6.1.4.1.14519.5.2.1.6279.6001.159996104466052855396410079250
+168,1.3.6.1.4.1.14519.5.2.1.6279.6001.160124400349792614505500125883
+169,1.3.6.1.4.1.14519.5.2.1.6279.6001.160216916075817913953530562493
+170,1.3.6.1.4.1.14519.5.2.1.6279.6001.160586340600816116143631200450
+171,1.3.6.1.4.1.14519.5.2.1.6279.6001.161002239822118346732951898613
+172,1.3.6.1.4.1.14519.5.2.1.6279.6001.161067514225109999586362698069
+173,1.3.6.1.4.1.14519.5.2.1.6279.6001.161073793312426102774780216551
+174,1.3.6.1.4.1.14519.5.2.1.6279.6001.161633200801003804714818844696
+175,1.3.6.1.4.1.14519.5.2.1.6279.6001.161821150841552408667852639317
+176,1.3.6.1.4.1.14519.5.2.1.6279.6001.161855583909753609742728521805
+177,1.3.6.1.4.1.14519.5.2.1.6279.6001.162207236104936931957809623059
+178,1.3.6.1.4.1.14519.5.2.1.6279.6001.162351539386551708034407968929
+179,1.3.6.1.4.1.14519.5.2.1.6279.6001.162718361851587451505896742103
+180,1.3.6.1.4.1.14519.5.2.1.6279.6001.162845309248822193437735868939
+181,1.3.6.1.4.1.14519.5.2.1.6279.6001.162901839201654862079549658100
+182,1.3.6.1.4.1.14519.5.2.1.6279.6001.163217526257871051722166468085
+183,1.3.6.1.4.1.14519.5.2.1.6279.6001.163901773171373940247829492387
+184,1.3.6.1.4.1.14519.5.2.1.6279.6001.163931625580639955914619627409
+185,1.3.6.1.4.1.14519.5.2.1.6279.6001.163994693532965040247348251579
+186,1.3.6.1.4.1.14519.5.2.1.6279.6001.164790817284381538042494285101
+187,1.3.6.1.4.1.14519.5.2.1.6279.6001.164988920331211858091402361989
+188,1.3.6.1.4.1.14519.5.2.1.6279.6001.167237290696350215427953159586
+189,1.3.6.1.4.1.14519.5.2.1.6279.6001.167500254299688235071950909530
+190,1.3.6.1.4.1.14519.5.2.1.6279.6001.167661207884826429102690781600
+191,1.3.6.1.4.1.14519.5.2.1.6279.6001.167919147233131417984739058859
+192,1.3.6.1.4.1.14519.5.2.1.6279.6001.168037818448885856452592057286
+193,1.3.6.1.4.1.14519.5.2.1.6279.6001.168605638657404145360275453085
+194,1.3.6.1.4.1.14519.5.2.1.6279.6001.168737928729363683423228050295
+195,1.3.6.1.4.1.14519.5.2.1.6279.6001.168833925301530155818375859047
+196,1.3.6.1.4.1.14519.5.2.1.6279.6001.168985655485163461062675655739
+197,1.3.6.1.4.1.14519.5.2.1.6279.6001.169128136262002764211589185953
+198,1.3.6.1.4.1.14519.5.2.1.6279.6001.170052181746004939527661217512
+199,1.3.6.1.4.1.14519.5.2.1.6279.6001.170706757615202213033480003264
+200,1.3.6.1.4.1.14519.5.2.1.6279.6001.170825539570536865106681134236
+201,1.3.6.1.4.1.14519.5.2.1.6279.6001.170921541362033046216100409521
+202,1.3.6.1.4.1.14519.5.2.1.6279.6001.171177995014336749670107905732
+203,1.3.6.1.4.1.14519.5.2.1.6279.6001.171667800241622018839592854574
+204,1.3.6.1.4.1.14519.5.2.1.6279.6001.171682845383273105440297561095
+205,1.3.6.1.4.1.14519.5.2.1.6279.6001.171919524048654494439256263785
+206,1.3.6.1.4.1.14519.5.2.1.6279.6001.172243743899615313644757844726
+207,1.3.6.1.4.1.14519.5.2.1.6279.6001.172573195301625265149778785969
+208,1.3.6.1.4.1.14519.5.2.1.6279.6001.172845185165807139298420209778
+209,1.3.6.1.4.1.14519.5.2.1.6279.6001.173101104804533997398137418032
+210,1.3.6.1.4.1.14519.5.2.1.6279.6001.173106154739244262091404659845
+211,1.3.6.1.4.1.14519.5.2.1.6279.6001.173556680294801532247454313511
+212,1.3.6.1.4.1.14519.5.2.1.6279.6001.173931884906244951746140865701
+213,1.3.6.1.4.1.14519.5.2.1.6279.6001.174168737938619557573021395302
+214,1.3.6.1.4.1.14519.5.2.1.6279.6001.174449669706458092793093760291
+215,1.3.6.1.4.1.14519.5.2.1.6279.6001.174692377730646477496286081479
+216,1.3.6.1.4.1.14519.5.2.1.6279.6001.174907798609768549012640380786
+217,1.3.6.1.4.1.14519.5.2.1.6279.6001.174935793360491516757154875981
+218,1.3.6.1.4.1.14519.5.2.1.6279.6001.175318131822744218104175746898
+219,1.3.6.1.4.1.14519.5.2.1.6279.6001.176030616406569931557298712518
+220,1.3.6.1.4.1.14519.5.2.1.6279.6001.176362912420491262783064585333
+221,1.3.6.1.4.1.14519.5.2.1.6279.6001.176638348958425792989125209419
+222,1.3.6.1.4.1.14519.5.2.1.6279.6001.176869045992276345870480098568
+223,1.3.6.1.4.1.14519.5.2.1.6279.6001.177086402277715068525592995222
+224,1.3.6.1.4.1.14519.5.2.1.6279.6001.177252583002664900748714851615
+225,1.3.6.1.4.1.14519.5.2.1.6279.6001.177685820605315926524514718990
+226,1.3.6.1.4.1.14519.5.2.1.6279.6001.177785764461425908755977367558
+227,1.3.6.1.4.1.14519.5.2.1.6279.6001.177888806135892723698313903329
+228,1.3.6.1.4.1.14519.5.2.1.6279.6001.177985905159808659201278495182
+229,1.3.6.1.4.1.14519.5.2.1.6279.6001.178391668569567816549737454720
+230,1.3.6.1.4.1.14519.5.2.1.6279.6001.178680586845223339579041794709
+231,1.3.6.1.4.1.14519.5.2.1.6279.6001.179049373636438705059720603192
+232,1.3.6.1.4.1.14519.5.2.1.6279.6001.179162671133894061547290922949
+233,1.3.6.1.4.1.14519.5.2.1.6279.6001.179209990684978588019929720099
+234,1.3.6.1.4.1.14519.5.2.1.6279.6001.179683407589764683292800449011
+235,1.3.6.1.4.1.14519.5.2.1.6279.6001.179730018513720561213088132029
+236,1.3.6.1.4.1.14519.5.2.1.6279.6001.179943248049071805421192715219
+237,1.3.6.1.4.1.14519.5.2.1.6279.6001.182192086929819295877506541021
+238,1.3.6.1.4.1.14519.5.2.1.6279.6001.182798854785392200340436516930
+239,1.3.6.1.4.1.14519.5.2.1.6279.6001.183056151780567460322586876100
+240,1.3.6.1.4.1.14519.5.2.1.6279.6001.183184435049555024219115904825
+241,1.3.6.1.4.1.14519.5.2.1.6279.6001.183843376225716802567192412456
+242,1.3.6.1.4.1.14519.5.2.1.6279.6001.183924380327950237519832859527
+243,1.3.6.1.4.1.14519.5.2.1.6279.6001.183982839679953938397312236359
+244,1.3.6.1.4.1.14519.5.2.1.6279.6001.184019785706727365023450012318
+245,1.3.6.1.4.1.14519.5.2.1.6279.6001.184412674007117333405073397832
+246,1.3.6.1.4.1.14519.5.2.1.6279.6001.185154482385982570363528682299
+247,1.3.6.1.4.1.14519.5.2.1.6279.6001.185226274332527104841463955058
+248,1.3.6.1.4.1.14519.5.2.1.6279.6001.186021279664749879526003668137
+249,1.3.6.1.4.1.14519.5.2.1.6279.6001.187108608022306504546286626125
+250,1.3.6.1.4.1.14519.5.2.1.6279.6001.187451715205085403623595258748
+251,1.3.6.1.4.1.14519.5.2.1.6279.6001.187694838527128312070807533473
+252,1.3.6.1.4.1.14519.5.2.1.6279.6001.187803155574314810830688534991
+253,1.3.6.1.4.1.14519.5.2.1.6279.6001.187966156856911682643615997798
+254,1.3.6.1.4.1.14519.5.2.1.6279.6001.188059920088313909273628445208
+255,1.3.6.1.4.1.14519.5.2.1.6279.6001.188209889686363159853715266493
+256,1.3.6.1.4.1.14519.5.2.1.6279.6001.188265424231150847356515802868
+257,1.3.6.1.4.1.14519.5.2.1.6279.6001.188376349804761988217597754952
+258,1.3.6.1.4.1.14519.5.2.1.6279.6001.188385286346390202873004762827
+259,1.3.6.1.4.1.14519.5.2.1.6279.6001.188484197846284733942365679565
+260,1.3.6.1.4.1.14519.5.2.1.6279.6001.188619674701053082195613114069
+261,1.3.6.1.4.1.14519.5.2.1.6279.6001.189483585244687808087477024767
+262,1.3.6.1.4.1.14519.5.2.1.6279.6001.190144948425835566841437565646
+263,1.3.6.1.4.1.14519.5.2.1.6279.6001.190298296009658115773239776160
+264,1.3.6.1.4.1.14519.5.2.1.6279.6001.190937805243443708408459490152
+265,1.3.6.1.4.1.14519.5.2.1.6279.6001.191266041369462391833537519639
+266,1.3.6.1.4.1.14519.5.2.1.6279.6001.191301539558980174217770205256
+267,1.3.6.1.4.1.14519.5.2.1.6279.6001.191617711875409989053242965150
+268,1.3.6.1.4.1.14519.5.2.1.6279.6001.192256506776434538421891524301
+269,1.3.6.1.4.1.14519.5.2.1.6279.6001.192419869605596446455526220766
+270,1.3.6.1.4.1.14519.5.2.1.6279.6001.193408384740507320589857096592
+271,1.3.6.1.4.1.14519.5.2.1.6279.6001.193721075067404532739943086458
+272,1.3.6.1.4.1.14519.5.2.1.6279.6001.193808128386712859512130599234
+273,1.3.6.1.4.1.14519.5.2.1.6279.6001.193964947698259739624715468431
+274,1.3.6.1.4.1.14519.5.2.1.6279.6001.194246472548954252250399902051
+275,1.3.6.1.4.1.14519.5.2.1.6279.6001.194440094986948071643661798326
+276,1.3.6.1.4.1.14519.5.2.1.6279.6001.194465340552956447447896167830
+277,1.3.6.1.4.1.14519.5.2.1.6279.6001.194488534645348916700259325236
+278,1.3.6.1.4.1.14519.5.2.1.6279.6001.194632613233275988184244485809
+279,1.3.6.1.4.1.14519.5.2.1.6279.6001.194766721609772924944646251928
+280,1.3.6.1.4.1.14519.5.2.1.6279.6001.195557219224169985110295082004
+281,1.3.6.1.4.1.14519.5.2.1.6279.6001.195913706607582347421429908613
+282,1.3.6.1.4.1.14519.5.2.1.6279.6001.196251645377731223510086726530
+283,1.3.6.1.4.1.14519.5.2.1.6279.6001.197063290812663596858124411210
+284,1.3.6.1.4.1.14519.5.2.1.6279.6001.197987940182806628828566429132
+285,1.3.6.1.4.1.14519.5.2.1.6279.6001.198016798894102791158686961192
+286,1.3.6.1.4.1.14519.5.2.1.6279.6001.198698492013538481395497694975
+287,1.3.6.1.4.1.14519.5.2.1.6279.6001.199069398344356765037879821616
+288,1.3.6.1.4.1.14519.5.2.1.6279.6001.199171741859530285887752432478
+289,1.3.6.1.4.1.14519.5.2.1.6279.6001.199220738144407033276946096708
+290,1.3.6.1.4.1.14519.5.2.1.6279.6001.199261544234308780356714831537
+291,1.3.6.1.4.1.14519.5.2.1.6279.6001.199282854229880908602362094937
+292,1.3.6.1.4.1.14519.5.2.1.6279.6001.199670099218798685977406484591
+293,1.3.6.1.4.1.14519.5.2.1.6279.6001.199975006921901879512837687266
+294,1.3.6.1.4.1.14519.5.2.1.6279.6001.200513183558872708878454294671
+295,1.3.6.1.4.1.14519.5.2.1.6279.6001.200558451375970945040979397866
+296,1.3.6.1.4.1.14519.5.2.1.6279.6001.200725988589959521302320481687
+297,1.3.6.1.4.1.14519.5.2.1.6279.6001.200837896655745926888305239398
+298,1.3.6.1.4.1.14519.5.2.1.6279.6001.200841000324240313648595016964
+299,1.3.6.1.4.1.14519.5.2.1.6279.6001.201890795870532056891161597218
+300,1.3.6.1.4.1.14519.5.2.1.6279.6001.202187810895588720702176009630
+301,1.3.6.1.4.1.14519.5.2.1.6279.6001.202283133206014258077705539227
+302,1.3.6.1.4.1.14519.5.2.1.6279.6001.202464973819273687476049035824
+303,1.3.6.1.4.1.14519.5.2.1.6279.6001.202476538079060560282495099956
+304,1.3.6.1.4.1.14519.5.2.1.6279.6001.202643836890896697853521610450
+305,1.3.6.1.4.1.14519.5.2.1.6279.6001.202811684116768680758082619196
+306,1.3.6.1.4.1.14519.5.2.1.6279.6001.203179378754043776171267611064
+307,1.3.6.1.4.1.14519.5.2.1.6279.6001.203425588524695836343069893813
+308,1.3.6.1.4.1.14519.5.2.1.6279.6001.203741923654363010377298352671
+309,1.3.6.1.4.1.14519.5.2.1.6279.6001.204287915902811325371247860532
+310,1.3.6.1.4.1.14519.5.2.1.6279.6001.204303454658845815034433453512
+311,1.3.6.1.4.1.14519.5.2.1.6279.6001.204566802718283633558802774757
+312,1.3.6.1.4.1.14519.5.2.1.6279.6001.204802250386343794613980417281
+313,1.3.6.1.4.1.14519.5.2.1.6279.6001.205523326998654833765855998037
+314,1.3.6.1.4.1.14519.5.2.1.6279.6001.205615524269596458818376243313
+315,1.3.6.1.4.1.14519.5.2.1.6279.6001.205852555362702089950453265567
+316,1.3.6.1.4.1.14519.5.2.1.6279.6001.205993750485568250373835565680
+317,1.3.6.1.4.1.14519.5.2.1.6279.6001.206028343897359374907954580114
+318,1.3.6.1.4.1.14519.5.2.1.6279.6001.206097113343059612247503064658
+319,1.3.6.1.4.1.14519.5.2.1.6279.6001.206539885154775002929031534291
+320,1.3.6.1.4.1.14519.5.2.1.6279.6001.207341668080525761926965850679
+321,1.3.6.1.4.1.14519.5.2.1.6279.6001.208511362832825683639135205368
+322,1.3.6.1.4.1.14519.5.2.1.6279.6001.208737629504245244513001631764
+323,1.3.6.1.4.1.14519.5.2.1.6279.6001.209269973797560820442292189762
+324,1.3.6.1.4.1.14519.5.2.1.6279.6001.210426531621179400035178209430
+325,1.3.6.1.4.1.14519.5.2.1.6279.6001.210837812047373739447725050963
+326,1.3.6.1.4.1.14519.5.2.1.6279.6001.211051626197585058967163339846
+327,1.3.6.1.4.1.14519.5.2.1.6279.6001.211071908915618528829547301883
+328,1.3.6.1.4.1.14519.5.2.1.6279.6001.211956804948320236390242845468
+329,1.3.6.1.4.1.14519.5.2.1.6279.6001.212346425055214308006918165305
+330,1.3.6.1.4.1.14519.5.2.1.6279.6001.212608679077007918190529579976
+331,1.3.6.1.4.1.14519.5.2.1.6279.6001.213022585153512920098588556742
+332,1.3.6.1.4.1.14519.5.2.1.6279.6001.213140617640021803112060161074
+333,1.3.6.1.4.1.14519.5.2.1.6279.6001.213854687290736562463866711534
+334,1.3.6.1.4.1.14519.5.2.1.6279.6001.214252223927572015414741039150
+335,1.3.6.1.4.1.14519.5.2.1.6279.6001.214800939017429618305208626314
+336,1.3.6.1.4.1.14519.5.2.1.6279.6001.215086589927307766627151367533
+337,1.3.6.1.4.1.14519.5.2.1.6279.6001.215104063467523905369326175410
+338,1.3.6.1.4.1.14519.5.2.1.6279.6001.215640837032688688030770057224
+339,1.3.6.1.4.1.14519.5.2.1.6279.6001.215785045378334625097907422785
+340,1.3.6.1.4.1.14519.5.2.1.6279.6001.216252660192313507027754194207
+341,1.3.6.1.4.1.14519.5.2.1.6279.6001.216526102138308489357443843021
+342,1.3.6.1.4.1.14519.5.2.1.6279.6001.216652640878960522552873394709
+343,1.3.6.1.4.1.14519.5.2.1.6279.6001.216882370221919561230873289517
+344,1.3.6.1.4.1.14519.5.2.1.6279.6001.217589936421986638139451480826
+345,1.3.6.1.4.1.14519.5.2.1.6279.6001.217697417596902141600884006982
+346,1.3.6.1.4.1.14519.5.2.1.6279.6001.217754016294471278921686508169
+347,1.3.6.1.4.1.14519.5.2.1.6279.6001.217955041973656886482758642958
+348,1.3.6.1.4.1.14519.5.2.1.6279.6001.218476624578721885561483687176
+349,1.3.6.1.4.1.14519.5.2.1.6279.6001.219087313261026510628926082729
+350,1.3.6.1.4.1.14519.5.2.1.6279.6001.219254430927834326484477690403
+351,1.3.6.1.4.1.14519.5.2.1.6279.6001.219281726101239572270900838145
+352,1.3.6.1.4.1.14519.5.2.1.6279.6001.219349715895470349269596532320
+353,1.3.6.1.4.1.14519.5.2.1.6279.6001.219428004988664846407984058588
+354,1.3.6.1.4.1.14519.5.2.1.6279.6001.219618492426142913407827034169
+355,1.3.6.1.4.1.14519.5.2.1.6279.6001.219909753224298157409438012179
+356,1.3.6.1.4.1.14519.5.2.1.6279.6001.220205300714852483483213840572
+357,1.3.6.1.4.1.14519.5.2.1.6279.6001.220596530836092324070084384692
+358,1.3.6.1.4.1.14519.5.2.1.6279.6001.221017801605543296514746423389
+359,1.3.6.1.4.1.14519.5.2.1.6279.6001.221945191226273284587353530424
+360,1.3.6.1.4.1.14519.5.2.1.6279.6001.222052723822248889877676736332
+361,1.3.6.1.4.1.14519.5.2.1.6279.6001.222087811960706096424718056430
+362,1.3.6.1.4.1.14519.5.2.1.6279.6001.223098610241551815995595311693
+363,1.3.6.1.4.1.14519.5.2.1.6279.6001.223650122819238796121876338881
+364,1.3.6.1.4.1.14519.5.2.1.6279.6001.224465398054769500989828256685
+365,1.3.6.1.4.1.14519.5.2.1.6279.6001.225154811831720426832024114593
+366,1.3.6.1.4.1.14519.5.2.1.6279.6001.225227615446398900698431118292
+367,1.3.6.1.4.1.14519.5.2.1.6279.6001.225515255547637437801620523312
+368,1.3.6.1.4.1.14519.5.2.1.6279.6001.226152078193253087875725735761
+369,1.3.6.1.4.1.14519.5.2.1.6279.6001.226383054119800793308721198594
+370,1.3.6.1.4.1.14519.5.2.1.6279.6001.226456162308124493341905600418
+371,1.3.6.1.4.1.14519.5.2.1.6279.6001.226564372605239604660221582288
+372,1.3.6.1.4.1.14519.5.2.1.6279.6001.226889213794065160713547677129
+373,1.3.6.1.4.1.14519.5.2.1.6279.6001.227707494413800460340110762069
+374,1.3.6.1.4.1.14519.5.2.1.6279.6001.227796349777753378641347819780
+375,1.3.6.1.4.1.14519.5.2.1.6279.6001.227885601428639043345478571594
+376,1.3.6.1.4.1.14519.5.2.1.6279.6001.227962600322799211676960828223
+377,1.3.6.1.4.1.14519.5.2.1.6279.6001.227968442353440630355230778531
+378,1.3.6.1.4.1.14519.5.2.1.6279.6001.228511122591230092662900221600
+379,1.3.6.1.4.1.14519.5.2.1.6279.6001.228934821089041845791238006047
+380,1.3.6.1.4.1.14519.5.2.1.6279.6001.229096941293122177107846044795
+381,1.3.6.1.4.1.14519.5.2.1.6279.6001.229171189693734694696158152904
+382,1.3.6.1.4.1.14519.5.2.1.6279.6001.229664630348267553620068691756
+383,1.3.6.1.4.1.14519.5.2.1.6279.6001.229860476925100292554329427970
+384,1.3.6.1.4.1.14519.5.2.1.6279.6001.229960820686439513664996214638
+385,1.3.6.1.4.1.14519.5.2.1.6279.6001.230078008964732806419498631442
+386,1.3.6.1.4.1.14519.5.2.1.6279.6001.230416590143922549745658357505
+387,1.3.6.1.4.1.14519.5.2.1.6279.6001.230491296081537726468075344411
+388,1.3.6.1.4.1.14519.5.2.1.6279.6001.230675342744370103160629638194
+389,1.3.6.1.4.1.14519.5.2.1.6279.6001.231002159523969307155990628066
+390,1.3.6.1.4.1.14519.5.2.1.6279.6001.231645134739451754302647733304
+391,1.3.6.1.4.1.14519.5.2.1.6279.6001.231834776365874788440767645596
+392,1.3.6.1.4.1.14519.5.2.1.6279.6001.232011770495640253949434620907
+393,1.3.6.1.4.1.14519.5.2.1.6279.6001.232058316950007760548968840196
+394,1.3.6.1.4.1.14519.5.2.1.6279.6001.232071262560365924176679652948
+395,1.3.6.1.4.1.14519.5.2.1.6279.6001.233001470265230594739708503198
+396,1.3.6.1.4.1.14519.5.2.1.6279.6001.233433352108264931671753343044
+397,1.3.6.1.4.1.14519.5.2.1.6279.6001.233652865358649579816568545171
+398,1.3.6.1.4.1.14519.5.2.1.6279.6001.234400932423244218697302970157
+399,1.3.6.1.4.1.14519.5.2.1.6279.6001.235217371152464582553341729176
+400,1.3.6.1.4.1.14519.5.2.1.6279.6001.235364978775280910367690540811
+401,1.3.6.1.4.1.14519.5.2.1.6279.6001.236698827306171960683086245994
+402,1.3.6.1.4.1.14519.5.2.1.6279.6001.237215747217294006286437405216
+403,1.3.6.1.4.1.14519.5.2.1.6279.6001.237428977311365557972720635401
+404,1.3.6.1.4.1.14519.5.2.1.6279.6001.237915456403882324748189195892
+405,1.3.6.1.4.1.14519.5.2.1.6279.6001.238019241099704094018548301753
+406,1.3.6.1.4.1.14519.5.2.1.6279.6001.238042459915048190592571019348
+407,1.3.6.1.4.1.14519.5.2.1.6279.6001.238522526736091851696274044574
+408,1.3.6.1.4.1.14519.5.2.1.6279.6001.238855414831158993232534884296
+409,1.3.6.1.4.1.14519.5.2.1.6279.6001.239358021703233250639913775427
+410,1.3.6.1.4.1.14519.5.2.1.6279.6001.240630002689062442926543993263
+411,1.3.6.1.4.1.14519.5.2.1.6279.6001.240969450540588211676803094518
+412,1.3.6.1.4.1.14519.5.2.1.6279.6001.241083615484551649610616348856
+413,1.3.6.1.4.1.14519.5.2.1.6279.6001.241570579760883349458693655367
+414,1.3.6.1.4.1.14519.5.2.1.6279.6001.241717018262666382493757419144
+415,1.3.6.1.4.1.14519.5.2.1.6279.6001.242624386080831911167122628616
+416,1.3.6.1.4.1.14519.5.2.1.6279.6001.242761658169703141430370511586
+417,1.3.6.1.4.1.14519.5.2.1.6279.6001.243094273518213382155770295147
+418,1.3.6.1.4.1.14519.5.2.1.6279.6001.244204120220889433826451158706
+419,1.3.6.1.4.1.14519.5.2.1.6279.6001.244442540088515471945035689377
+420,1.3.6.1.4.1.14519.5.2.1.6279.6001.244447966386688625240438849169
+421,1.3.6.1.4.1.14519.5.2.1.6279.6001.244590453955380448651329424024
+422,1.3.6.1.4.1.14519.5.2.1.6279.6001.244681063194071446501270815660
+423,1.3.6.1.4.1.14519.5.2.1.6279.6001.245248446973732759194067808002
+424,1.3.6.1.4.1.14519.5.2.1.6279.6001.245349763807614756148761326488
+425,1.3.6.1.4.1.14519.5.2.1.6279.6001.245391706475696258069508046497
+426,1.3.6.1.4.1.14519.5.2.1.6279.6001.245546033414728092794968890929
+427,1.3.6.1.4.1.14519.5.2.1.6279.6001.246178337114401749164850220976
+428,1.3.6.1.4.1.14519.5.2.1.6279.6001.246225645401227472829175288633
+429,1.3.6.1.4.1.14519.5.2.1.6279.6001.246589849815292078281051154201
+430,1.3.6.1.4.1.14519.5.2.1.6279.6001.246758220302211646532176593724
+431,1.3.6.1.4.1.14519.5.2.1.6279.6001.247060297988514823071467295949
+432,1.3.6.1.4.1.14519.5.2.1.6279.6001.247769845138587733933485039556
+433,1.3.6.1.4.1.14519.5.2.1.6279.6001.247816269490470394602288565775
+434,1.3.6.1.4.1.14519.5.2.1.6279.6001.248357157975955379661896491341
+435,1.3.6.1.4.1.14519.5.2.1.6279.6001.248360766706804179966476685510
+436,1.3.6.1.4.1.14519.5.2.1.6279.6001.248425363469507808613979846863
+437,1.3.6.1.4.1.14519.5.2.1.6279.6001.249032660919473722154870746474
+438,1.3.6.1.4.1.14519.5.2.1.6279.6001.249314567767437206995861966896
+439,1.3.6.1.4.1.14519.5.2.1.6279.6001.249404938669582150398726875826
+440,1.3.6.1.4.1.14519.5.2.1.6279.6001.249450003033735700817635168066
+441,1.3.6.1.4.1.14519.5.2.1.6279.6001.249530219848512542668813996730
+442,1.3.6.1.4.1.14519.5.2.1.6279.6001.250397690690072950000431855143
+443,1.3.6.1.4.1.14519.5.2.1.6279.6001.250438451287314206124484591986
+444,1.3.6.1.4.1.14519.5.2.1.6279.6001.250481236093201801255751845296
+445,1.3.6.1.4.1.14519.5.2.1.6279.6001.250863365157630276148828903732
+446,1.3.6.1.4.1.14519.5.2.1.6279.6001.251215764736737018371915284679
+447,1.3.6.1.4.1.14519.5.2.1.6279.6001.252358625003143649770119512644
+448,1.3.6.1.4.1.14519.5.2.1.6279.6001.252634638822000832774167856951
+449,1.3.6.1.4.1.14519.5.2.1.6279.6001.252697338970999211181671881792
+450,1.3.6.1.4.1.14519.5.2.1.6279.6001.252709517998555732486024866345
+451,1.3.6.1.4.1.14519.5.2.1.6279.6001.252814707117018427472206147014
+452,1.3.6.1.4.1.14519.5.2.1.6279.6001.253283426904813468115158375647
+453,1.3.6.1.4.1.14519.5.2.1.6279.6001.253317247142837717905329340520
+454,1.3.6.1.4.1.14519.5.2.1.6279.6001.253322967203074795232627653819
+455,1.3.6.1.4.1.14519.5.2.1.6279.6001.254138388912084634057282064266
+456,1.3.6.1.4.1.14519.5.2.1.6279.6001.254254303842550572473665729969
+457,1.3.6.1.4.1.14519.5.2.1.6279.6001.254473943359963613733707320244
+458,1.3.6.1.4.1.14519.5.2.1.6279.6001.254929810944557499537650429296
+459,1.3.6.1.4.1.14519.5.2.1.6279.6001.254957696184671649675053562027
+460,1.3.6.1.4.1.14519.5.2.1.6279.6001.255409701134762680010928250229
+461,1.3.6.1.4.1.14519.5.2.1.6279.6001.255999614855292116767517149228
+462,1.3.6.1.4.1.14519.5.2.1.6279.6001.256542095129414948017808425649
+463,1.3.6.1.4.1.14519.5.2.1.6279.6001.257383535269991165447822992959
+464,1.3.6.1.4.1.14519.5.2.1.6279.6001.257515388956260258681136624817
+465,1.3.6.1.4.1.14519.5.2.1.6279.6001.257840703452266097926250569223
+466,1.3.6.1.4.1.14519.5.2.1.6279.6001.258220324170977900491673635112
+467,1.3.6.1.4.1.14519.5.2.1.6279.6001.259018373683540453277752706262
+468,1.3.6.1.4.1.14519.5.2.1.6279.6001.259123825760999546551970425757
+469,1.3.6.1.4.1.14519.5.2.1.6279.6001.259124675432205040899951626253
+470,1.3.6.1.4.1.14519.5.2.1.6279.6001.259227883564429312164962953756
+471,1.3.6.1.4.1.14519.5.2.1.6279.6001.259453428008507791234730686014
+472,1.3.6.1.4.1.14519.5.2.1.6279.6001.259543921154154401875872845498
+473,1.3.6.1.4.1.14519.5.2.1.6279.6001.261678072503577216586082745513
+474,1.3.6.1.4.1.14519.5.2.1.6279.6001.261700367741314729940340271960
+475,1.3.6.1.4.1.14519.5.2.1.6279.6001.262736997975960398949912434623
+476,1.3.6.1.4.1.14519.5.2.1.6279.6001.262873069163227096134627700599
+477,1.3.6.1.4.1.14519.5.2.1.6279.6001.264090899378396711987322794314
+478,1.3.6.1.4.1.14519.5.2.1.6279.6001.264251211689085893915477907261
+479,1.3.6.1.4.1.14519.5.2.1.6279.6001.265133389948279331857097127422
+480,1.3.6.1.4.1.14519.5.2.1.6279.6001.265453131727473342790950829556
+481,1.3.6.1.4.1.14519.5.2.1.6279.6001.265570697208310960298668720669
+482,1.3.6.1.4.1.14519.5.2.1.6279.6001.265775376735520890308424143898
+483,1.3.6.1.4.1.14519.5.2.1.6279.6001.265780642925621389994857727416
+484,1.3.6.1.4.1.14519.5.2.1.6279.6001.265960756233787099041040311282
+485,1.3.6.1.4.1.14519.5.2.1.6279.6001.266009527139315622265711325223
+486,1.3.6.1.4.1.14519.5.2.1.6279.6001.266581250778073944645044950856
+487,1.3.6.1.4.1.14519.5.2.1.6279.6001.267519732763035023633235877753
+488,1.3.6.1.4.1.14519.5.2.1.6279.6001.267957701183569638795986183786
+489,1.3.6.1.4.1.14519.5.2.1.6279.6001.268030488196493755113553009785
+490,1.3.6.1.4.1.14519.5.2.1.6279.6001.268589491017129166376960414534
+491,1.3.6.1.4.1.14519.5.2.1.6279.6001.268838889380981659524993261082
+492,1.3.6.1.4.1.14519.5.2.1.6279.6001.268992195564407418480563388746
+493,1.3.6.1.4.1.14519.5.2.1.6279.6001.269075535958871753309238331179
+494,1.3.6.1.4.1.14519.5.2.1.6279.6001.269689294231892620436462818860
+495,1.3.6.1.4.1.14519.5.2.1.6279.6001.270152671889301412052226973069
+496,1.3.6.1.4.1.14519.5.2.1.6279.6001.270215889102603268207599305185
+497,1.3.6.1.4.1.14519.5.2.1.6279.6001.270390050141765094612147226290
+498,1.3.6.1.4.1.14519.5.2.1.6279.6001.270788655216695628640355888562
+499,1.3.6.1.4.1.14519.5.2.1.6279.6001.270951128717816232360812849541
+500,1.3.6.1.4.1.14519.5.2.1.6279.6001.271220641987745483198036913951
+501,1.3.6.1.4.1.14519.5.2.1.6279.6001.271307051432838466826189754230
+502,1.3.6.1.4.1.14519.5.2.1.6279.6001.272042302501586336192628818865
+503,1.3.6.1.4.1.14519.5.2.1.6279.6001.272123398257168239653655006815
+504,1.3.6.1.4.1.14519.5.2.1.6279.6001.272190966764020277652079081128
+505,1.3.6.1.4.1.14519.5.2.1.6279.6001.272259794130271010519952623746
+506,1.3.6.1.4.1.14519.5.2.1.6279.6001.272344603176687884771013620823
+507,1.3.6.1.4.1.14519.5.2.1.6279.6001.272348349298439120568330857680
+508,1.3.6.1.4.1.14519.5.2.1.6279.6001.272961322147784625028175033640
+509,1.3.6.1.4.1.14519.5.2.1.6279.6001.273525289046256012743471155680
+510,1.3.6.1.4.1.14519.5.2.1.6279.6001.274052674198758621258447180130
+511,1.3.6.1.4.1.14519.5.2.1.6279.6001.275007193025729362844652516689
+512,1.3.6.1.4.1.14519.5.2.1.6279.6001.275755514659958628040305922764
+513,1.3.6.1.4.1.14519.5.2.1.6279.6001.275766318636944297772360944907
+514,1.3.6.1.4.1.14519.5.2.1.6279.6001.275849601663847251574860892603
+515,1.3.6.1.4.1.14519.5.2.1.6279.6001.275986221854423197884953496664
+516,1.3.6.1.4.1.14519.5.2.1.6279.6001.276351267409869539593937734609
+517,1.3.6.1.4.1.14519.5.2.1.6279.6001.276556509002726404418399209377
+518,1.3.6.1.4.1.14519.5.2.1.6279.6001.276710697414087561012670296643
+519,1.3.6.1.4.1.14519.5.2.1.6279.6001.277445975068759205899107114231
+520,1.3.6.1.4.1.14519.5.2.1.6279.6001.277452631455527999380186898011
+521,1.3.6.1.4.1.14519.5.2.1.6279.6001.277662902666135640561346462196
+522,1.3.6.1.4.1.14519.5.2.1.6279.6001.278010349511857248000260557753
+523,1.3.6.1.4.1.14519.5.2.1.6279.6001.278660284797073139172446973682
+524,1.3.6.1.4.1.14519.5.2.1.6279.6001.279300249795483097365868125932
+525,1.3.6.1.4.1.14519.5.2.1.6279.6001.279953669991076107785464313394
+526,1.3.6.1.4.1.14519.5.2.1.6279.6001.280072876841890439628529365478
+527,1.3.6.1.4.1.14519.5.2.1.6279.6001.280125803152924778388346920341
+528,1.3.6.1.4.1.14519.5.2.1.6279.6001.280972147860943609388015648430
+529,1.3.6.1.4.1.14519.5.2.1.6279.6001.281489753704424911132261151767
+530,1.3.6.1.4.1.14519.5.2.1.6279.6001.281967919138248195763602360723
+531,1.3.6.1.4.1.14519.5.2.1.6279.6001.282512043257574309474415322775
+532,1.3.6.1.4.1.14519.5.2.1.6279.6001.282779922503707013097174625409
+533,1.3.6.1.4.1.14519.5.2.1.6279.6001.283569726884265181140892667131
+534,1.3.6.1.4.1.14519.5.2.1.6279.6001.283733738239331719775105586296
+535,1.3.6.1.4.1.14519.5.2.1.6279.6001.283878926524838648426928238498
+536,1.3.6.1.4.1.14519.5.2.1.6279.6001.285926554490515269336267972830
+537,1.3.6.1.4.1.14519.5.2.1.6279.6001.286061375572911414226912429210
+538,1.3.6.1.4.1.14519.5.2.1.6279.6001.286217539434358186648717203667
+539,1.3.6.1.4.1.14519.5.2.1.6279.6001.286422846896797433168187085942
+540,1.3.6.1.4.1.14519.5.2.1.6279.6001.286627485198831346082954437212
+541,1.3.6.1.4.1.14519.5.2.1.6279.6001.286647622786041008124419915089
+542,1.3.6.1.4.1.14519.5.2.1.6279.6001.287560874054243719452635194040
+543,1.3.6.1.4.1.14519.5.2.1.6279.6001.287966244644280690737019247886
+544,1.3.6.1.4.1.14519.5.2.1.6279.6001.288701997968615460794642979503
+545,1.3.6.1.4.1.14519.5.2.1.6279.6001.290135156874098366424871975734
+546,1.3.6.1.4.1.14519.5.2.1.6279.6001.290410217650314119074833254861
+547,1.3.6.1.4.1.14519.5.2.1.6279.6001.291156498203266896953765649282
+548,1.3.6.1.4.1.14519.5.2.1.6279.6001.291539125579672469833850180824
+549,1.3.6.1.4.1.14519.5.2.1.6279.6001.292049618819567427252971059233
+550,1.3.6.1.4.1.14519.5.2.1.6279.6001.292057261351416339496913597985
+551,1.3.6.1.4.1.14519.5.2.1.6279.6001.292194861362266467652267941663
+552,1.3.6.1.4.1.14519.5.2.1.6279.6001.292576688635952269497781991202
+553,1.3.6.1.4.1.14519.5.2.1.6279.6001.292994770358625142596171316474
+554,1.3.6.1.4.1.14519.5.2.1.6279.6001.293593766328917170359373773080
+555,1.3.6.1.4.1.14519.5.2.1.6279.6001.293757615532132808762625441831
+556,1.3.6.1.4.1.14519.5.2.1.6279.6001.294120933998772507043263238704
+557,1.3.6.1.4.1.14519.5.2.1.6279.6001.294188507421106424248264912111
+558,1.3.6.1.4.1.14519.5.2.1.6279.6001.295298571102631191572192562523
+559,1.3.6.1.4.1.14519.5.2.1.6279.6001.295420274214095686326263147663
+560,1.3.6.1.4.1.14519.5.2.1.6279.6001.295462530340364058116953738925
+561,1.3.6.1.4.1.14519.5.2.1.6279.6001.296066944953051278419805374238
+562,1.3.6.1.4.1.14519.5.2.1.6279.6001.296738183013079390785739615169
+563,1.3.6.1.4.1.14519.5.2.1.6279.6001.296863826932699509516219450076
+564,1.3.6.1.4.1.14519.5.2.1.6279.6001.297251044869095073091780740645
+565,1.3.6.1.4.1.14519.5.2.1.6279.6001.297433269262659217151107535012
+566,1.3.6.1.4.1.14519.5.2.1.6279.6001.297964221542942838344351735414
+567,1.3.6.1.4.1.14519.5.2.1.6279.6001.297988578825170426663869669862
+568,1.3.6.1.4.1.14519.5.2.1.6279.6001.299476369290630280560355838785
+569,1.3.6.1.4.1.14519.5.2.1.6279.6001.299767339686526858593516834230
+570,1.3.6.1.4.1.14519.5.2.1.6279.6001.299806338046301317870803017534
+571,1.3.6.1.4.1.14519.5.2.1.6279.6001.300136985030081433029390459071
+572,1.3.6.1.4.1.14519.5.2.1.6279.6001.300146276266881736689307479986
+573,1.3.6.1.4.1.14519.5.2.1.6279.6001.300246184547502297539521283806
+574,1.3.6.1.4.1.14519.5.2.1.6279.6001.300270516469599170290456821227
+575,1.3.6.1.4.1.14519.5.2.1.6279.6001.300271604576987336866436407488
+576,1.3.6.1.4.1.14519.5.2.1.6279.6001.300392272203629213913702120739
+577,1.3.6.1.4.1.14519.5.2.1.6279.6001.300693623747082239407271583452
+578,1.3.6.1.4.1.14519.5.2.1.6279.6001.301462380687644451483231621986
+579,1.3.6.1.4.1.14519.5.2.1.6279.6001.301582691063019848479942618641
+580,1.3.6.1.4.1.14519.5.2.1.6279.6001.302134342469412607966016057827
+581,1.3.6.1.4.1.14519.5.2.1.6279.6001.302403227435841351528721627052
+582,1.3.6.1.4.1.14519.5.2.1.6279.6001.302557165094691896097534021075
+583,1.3.6.1.4.1.14519.5.2.1.6279.6001.303066851236267189733420290986
+584,1.3.6.1.4.1.14519.5.2.1.6279.6001.303421828981831854739626597495
+585,1.3.6.1.4.1.14519.5.2.1.6279.6001.303865116731361029078599241306
+586,1.3.6.1.4.1.14519.5.2.1.6279.6001.304676828064484590312919543151
+587,1.3.6.1.4.1.14519.5.2.1.6279.6001.304700823314998198591652152637
+588,1.3.6.1.4.1.14519.5.2.1.6279.6001.305858704835252413616501469037
+589,1.3.6.1.4.1.14519.5.2.1.6279.6001.305887072264491016857673607285
+590,1.3.6.1.4.1.14519.5.2.1.6279.6001.306112617218006614029386065035
+591,1.3.6.1.4.1.14519.5.2.1.6279.6001.306140003699110313373771452136
+592,1.3.6.1.4.1.14519.5.2.1.6279.6001.306520140119968755187868602181
+593,1.3.6.1.4.1.14519.5.2.1.6279.6001.306558074682524259000586270818
+594,1.3.6.1.4.1.14519.5.2.1.6279.6001.306788423710427765311352901943
+595,1.3.6.1.4.1.14519.5.2.1.6279.6001.306948744223170422945185006551
+596,1.3.6.1.4.1.14519.5.2.1.6279.6001.307835307280028057486413359377
+597,1.3.6.1.4.1.14519.5.2.1.6279.6001.307921770358136677021532761235
+598,1.3.6.1.4.1.14519.5.2.1.6279.6001.307946352302138765071461362398
+599,1.3.6.1.4.1.14519.5.2.1.6279.6001.308153138776443962077214577161
+600,1.3.6.1.4.1.14519.5.2.1.6279.6001.308183340111270052562662456038
+601,1.3.6.1.4.1.14519.5.2.1.6279.6001.308655308958459380153492314021
+602,1.3.6.1.4.1.14519.5.2.1.6279.6001.309672797925724868457151381131
+603,1.3.6.1.4.1.14519.5.2.1.6279.6001.309901913847714156367981722205
+604,1.3.6.1.4.1.14519.5.2.1.6279.6001.309955814083231537823157605135
+605,1.3.6.1.4.1.14519.5.2.1.6279.6001.309955999522338651429118207446
+606,1.3.6.1.4.1.14519.5.2.1.6279.6001.310395752124284049604069960014
+607,1.3.6.1.4.1.14519.5.2.1.6279.6001.310548927038333190233889983845
+608,1.3.6.1.4.1.14519.5.2.1.6279.6001.310626494937915759224334597176
+609,1.3.6.1.4.1.14519.5.2.1.6279.6001.311236942972970815890902714604
+610,1.3.6.1.4.1.14519.5.2.1.6279.6001.311476128731958142981941696518
+611,1.3.6.1.4.1.14519.5.2.1.6279.6001.311981398931043315779172047718
+612,1.3.6.1.4.1.14519.5.2.1.6279.6001.312127933722985204808706697221
+613,1.3.6.1.4.1.14519.5.2.1.6279.6001.312704771348460502013249647868
+614,1.3.6.1.4.1.14519.5.2.1.6279.6001.313283554967554803238484128406
+615,1.3.6.1.4.1.14519.5.2.1.6279.6001.313334055029671473836954456733
+616,1.3.6.1.4.1.14519.5.2.1.6279.6001.313605260055394498989743099991
+617,1.3.6.1.4.1.14519.5.2.1.6279.6001.313756547848086902190878548835
+618,1.3.6.1.4.1.14519.5.2.1.6279.6001.313835996725364342034830119490
+619,1.3.6.1.4.1.14519.5.2.1.6279.6001.314519596680450457855054746285
+620,1.3.6.1.4.1.14519.5.2.1.6279.6001.314789075871001236641548593165
+621,1.3.6.1.4.1.14519.5.2.1.6279.6001.314836406260772370397541392345
+622,1.3.6.1.4.1.14519.5.2.1.6279.6001.315187221221054114974341475212
+623,1.3.6.1.4.1.14519.5.2.1.6279.6001.315214756157389122376518747372
+624,1.3.6.1.4.1.14519.5.2.1.6279.6001.315770913282450940389971401304
+625,1.3.6.1.4.1.14519.5.2.1.6279.6001.315918264676377418120578391325
+626,1.3.6.1.4.1.14519.5.2.1.6279.6001.316393351033132458296975008261
+627,1.3.6.1.4.1.14519.5.2.1.6279.6001.316900421002460665752357657094
+628,1.3.6.1.4.1.14519.5.2.1.6279.6001.316911475886263032009840828684
+629,1.3.6.1.4.1.14519.5.2.1.6279.6001.317087518531899043292346860596
+630,1.3.6.1.4.1.14519.5.2.1.6279.6001.317613170669207528926259976488
+631,1.3.6.1.4.1.14519.5.2.1.6279.6001.319009811633846643966578282371
+632,1.3.6.1.4.1.14519.5.2.1.6279.6001.319066480138812986026181758474
+633,1.3.6.1.4.1.14519.5.2.1.6279.6001.320111824803959660037459294083
+634,1.3.6.1.4.1.14519.5.2.1.6279.6001.320967206808467952819309001585
+635,1.3.6.1.4.1.14519.5.2.1.6279.6001.321465552859463184018938648244
+636,1.3.6.1.4.1.14519.5.2.1.6279.6001.321935195060268166151738328001
+637,1.3.6.1.4.1.14519.5.2.1.6279.6001.323302986710576400812869264321
+638,1.3.6.1.4.1.14519.5.2.1.6279.6001.323408652979949774528873200770
+639,1.3.6.1.4.1.14519.5.2.1.6279.6001.323426705628838942177546503237
+640,1.3.6.1.4.1.14519.5.2.1.6279.6001.323535944958374186208096541480
+641,1.3.6.1.4.1.14519.5.2.1.6279.6001.323541312620128092852212458228
+642,1.3.6.1.4.1.14519.5.2.1.6279.6001.323753921818102744511069914832
+643,1.3.6.1.4.1.14519.5.2.1.6279.6001.323859712968543712594665815359
+644,1.3.6.1.4.1.14519.5.2.1.6279.6001.323899724653546164058849558431
+645,1.3.6.1.4.1.14519.5.2.1.6279.6001.324290109423920971676288828329
+646,1.3.6.1.4.1.14519.5.2.1.6279.6001.324567010179873305471925391582
+647,1.3.6.1.4.1.14519.5.2.1.6279.6001.324649110927013926557500550446
+648,1.3.6.1.4.1.14519.5.2.1.6279.6001.325164338773720548739146851679
+649,1.3.6.1.4.1.14519.5.2.1.6279.6001.325580698241281352835338693869
+650,1.3.6.1.4.1.14519.5.2.1.6279.6001.326057189095429101398977448288
+651,1.3.6.1.4.1.14519.5.2.1.6279.6001.328695385904874796172316226975
+652,1.3.6.1.4.1.14519.5.2.1.6279.6001.328789598898469177563438457842
+653,1.3.6.1.4.1.14519.5.2.1.6279.6001.328944769569002417592093467626
+654,1.3.6.1.4.1.14519.5.2.1.6279.6001.329326052298830421573852261436
+655,1.3.6.1.4.1.14519.5.2.1.6279.6001.329404588567903628160652715124
+656,1.3.6.1.4.1.14519.5.2.1.6279.6001.329624439086643515259182406526
+657,1.3.6.1.4.1.14519.5.2.1.6279.6001.330043769832606379655473292782
+658,1.3.6.1.4.1.14519.5.2.1.6279.6001.330425234131526435132846006585
+659,1.3.6.1.4.1.14519.5.2.1.6279.6001.330544495001617450666819906758
+660,1.3.6.1.4.1.14519.5.2.1.6279.6001.330643702676971528301859647742
+661,1.3.6.1.4.1.14519.5.2.1.6279.6001.331211682377519763144559212009
+662,1.3.6.1.4.1.14519.5.2.1.6279.6001.332453873575389860371315979768
+663,1.3.6.1.4.1.14519.5.2.1.6279.6001.332829333783605240302521201463
+664,1.3.6.1.4.1.14519.5.2.1.6279.6001.333145094436144085379032922488
+665,1.3.6.1.4.1.14519.5.2.1.6279.6001.333319057944372470283038483725
+666,1.3.6.1.4.1.14519.5.2.1.6279.6001.334022941831199910030220864961
+667,1.3.6.1.4.1.14519.5.2.1.6279.6001.334105754605642100456249422350
+668,1.3.6.1.4.1.14519.5.2.1.6279.6001.334166493392278943610545989413
+669,1.3.6.1.4.1.14519.5.2.1.6279.6001.334184846571549530235084187602
+670,1.3.6.1.4.1.14519.5.2.1.6279.6001.334517907433161353885866806005
+671,1.3.6.1.4.1.14519.5.2.1.6279.6001.335866409407244673864352309754
+672,1.3.6.1.4.1.14519.5.2.1.6279.6001.336102335330125765000317290445
+673,1.3.6.1.4.1.14519.5.2.1.6279.6001.336198008634390022174744544656
+674,1.3.6.1.4.1.14519.5.2.1.6279.6001.336225579776978874775723463327
+675,1.3.6.1.4.1.14519.5.2.1.6279.6001.336894364358709782463716339027
+676,1.3.6.1.4.1.14519.5.2.1.6279.6001.337005960787660957389988207064
+677,1.3.6.1.4.1.14519.5.2.1.6279.6001.337845202462615014431060697507
+678,1.3.6.1.4.1.14519.5.2.1.6279.6001.338104567770715523699587505022
+679,1.3.6.1.4.1.14519.5.2.1.6279.6001.338114620394879648539943280992
+680,1.3.6.1.4.1.14519.5.2.1.6279.6001.338447145504282422142824032832
+681,1.3.6.1.4.1.14519.5.2.1.6279.6001.338875090785618956575597613546
+682,1.3.6.1.4.1.14519.5.2.1.6279.6001.339039410276356623209709113755
+683,1.3.6.1.4.1.14519.5.2.1.6279.6001.339142594937666268384335506819
+684,1.3.6.1.4.1.14519.5.2.1.6279.6001.339484970190920330170416228517
+685,1.3.6.1.4.1.14519.5.2.1.6279.6001.339546614783708685476232944897
+686,1.3.6.1.4.1.14519.5.2.1.6279.6001.339882192295517122002429068974
+687,1.3.6.1.4.1.14519.5.2.1.6279.6001.340012777775661021262977442176
+688,1.3.6.1.4.1.14519.5.2.1.6279.6001.340158437895922179455019686521
+689,1.3.6.1.4.1.14519.5.2.1.6279.6001.341557859428950960906150406596
+690,1.3.6.1.4.1.14519.5.2.1.6279.6001.346115813056769250958550383763
+691,1.3.6.1.4.1.14519.5.2.1.6279.6001.362762275895885013176610377950
+692,1.3.6.1.4.1.14519.5.2.1.6279.6001.367204840301639918160517361062
+693,1.3.6.1.4.1.14519.5.2.1.6279.6001.373433682859788429397781158572
+694,1.3.6.1.4.1.14519.5.2.1.6279.6001.385151742584074711135621089321
+695,1.3.6.1.4.1.14519.5.2.1.6279.6001.387954549120924524005910602207
+696,1.3.6.1.4.1.14519.5.2.1.6279.6001.390009458146468860187238398197
+697,1.3.6.1.4.1.14519.5.2.1.6279.6001.390513733720659266816639651938
+698,1.3.6.1.4.1.14519.5.2.1.6279.6001.392861216720727557882279374324
+699,1.3.6.1.4.1.14519.5.2.1.6279.6001.394470743585708729682444806008
+700,1.3.6.1.4.1.14519.5.2.1.6279.6001.395623571499047043765181005112
+701,1.3.6.1.4.1.14519.5.2.1.6279.6001.397062004302272014259317520874
+702,1.3.6.1.4.1.14519.5.2.1.6279.6001.397202838387416555106806022938
+703,1.3.6.1.4.1.14519.5.2.1.6279.6001.397522780537301776672854630421
+704,1.3.6.1.4.1.14519.5.2.1.6279.6001.398955972049286139436103068984
+705,1.3.6.1.4.1.14519.5.2.1.6279.6001.401389720232123950202941034290
+706,1.3.6.1.4.1.14519.5.2.1.6279.6001.404364125369979066736354549484
+707,1.3.6.1.4.1.14519.5.2.1.6279.6001.404457313935200882843898832756
+708,1.3.6.1.4.1.14519.5.2.1.6279.6001.404768898286087278137462774930
+709,1.3.6.1.4.1.14519.5.2.1.6279.6001.413896555982844732694353377538
+710,1.3.6.1.4.1.14519.5.2.1.6279.6001.414288023902112119945238126594
+711,1.3.6.1.4.1.14519.5.2.1.6279.6001.416701701108520592702405866796
+712,1.3.6.1.4.1.14519.5.2.1.6279.6001.417815314896088956784723476543
+713,1.3.6.1.4.1.14519.5.2.1.6279.6001.419601611032172899567156073142
+714,1.3.6.1.4.1.14519.5.2.1.6279.6001.428038562098395445838061018440
+715,1.3.6.1.4.1.14519.5.2.1.6279.6001.430109407146633213496148200410
+716,1.3.6.1.4.1.14519.5.2.1.6279.6001.436403998650924660479049012235
+717,1.3.6.1.4.1.14519.5.2.1.6279.6001.438308540025607517017949816111
+718,1.3.6.1.4.1.14519.5.2.1.6279.6001.439153572396640163898529626096
+719,1.3.6.1.4.1.14519.5.2.1.6279.6001.440226700369921575481834344455
+720,1.3.6.1.4.1.14519.5.2.1.6279.6001.443400977949406454649939526179
+721,1.3.6.1.4.1.14519.5.2.1.6279.6001.447468612991222399440694673357
+722,1.3.6.1.4.1.14519.5.2.1.6279.6001.449254134266555649028108149727
+723,1.3.6.1.4.1.14519.5.2.1.6279.6001.450501966058662668272378865145
+724,1.3.6.1.4.1.14519.5.2.1.6279.6001.454273545863197752384437758130
+725,1.3.6.1.4.1.14519.5.2.1.6279.6001.458525794434429386945463560826
+726,1.3.6.1.4.1.14519.5.2.1.6279.6001.461155505515403114280165935891
+727,1.3.6.1.4.1.14519.5.2.1.6279.6001.463214953282361219537913355115
+728,1.3.6.1.4.1.14519.5.2.1.6279.6001.463588161905537526756964393219
+729,1.3.6.1.4.1.14519.5.2.1.6279.6001.465032801496479029639448332481
+730,1.3.6.1.4.1.14519.5.2.1.6279.6001.466284753932369813717081722101
+731,1.3.6.1.4.1.14519.5.2.1.6279.6001.470912100568074901744259213968
+732,1.3.6.1.4.1.14519.5.2.1.6279.6001.472487466001405705666001578363
+733,1.3.6.1.4.1.14519.5.2.1.6279.6001.475325201787910087416720919680
+734,1.3.6.1.4.1.14519.5.2.1.6279.6001.478062284228419671253422844986
+735,1.3.6.1.4.1.14519.5.2.1.6279.6001.479402560265137632920333093071
+736,1.3.6.1.4.1.14519.5.2.1.6279.6001.481278873893653517789960724156
+737,1.3.6.1.4.1.14519.5.2.1.6279.6001.483655032093002252444764787700
+738,1.3.6.1.4.1.14519.5.2.1.6279.6001.486999111981013268988489262668
+739,1.3.6.1.4.1.14519.5.2.1.6279.6001.487268565754493433372433148666
+740,1.3.6.1.4.1.14519.5.2.1.6279.6001.487745546557477250336016826588
+741,1.3.6.1.4.1.14519.5.2.1.6279.6001.503980049263254396021509831276
+742,1.3.6.1.4.1.14519.5.2.1.6279.6001.504324996863016748259361352296
+743,1.3.6.1.4.1.14519.5.2.1.6279.6001.504845428620607044098514803031
+744,1.3.6.1.4.1.14519.5.2.1.6279.6001.511347030803753100045216493273
+745,1.3.6.1.4.1.14519.5.2.1.6279.6001.513023675145166449943177283490
+746,1.3.6.1.4.1.14519.5.2.1.6279.6001.518487185634324801733841260431
+747,1.3.6.1.4.1.14519.5.2.1.6279.6001.525937963993475482158828421281
+748,1.3.6.1.4.1.14519.5.2.1.6279.6001.534006575256943390479252771547
+749,1.3.6.1.4.1.14519.5.2.1.6279.6001.534083630500464995109143618896
+750,1.3.6.1.4.1.14519.5.2.1.6279.6001.550599855064600241623943717588
+751,1.3.6.1.4.1.14519.5.2.1.6279.6001.553241901808946577644850294647
+752,1.3.6.1.4.1.14519.5.2.1.6279.6001.557875302364105947813979213632
+753,1.3.6.1.4.1.14519.5.2.1.6279.6001.558286136379689377915919180358
+754,1.3.6.1.4.1.14519.5.2.1.6279.6001.561423049201987049884663740668
+755,1.3.6.1.4.1.14519.5.2.1.6279.6001.561458563853929400124470098603
+756,1.3.6.1.4.1.14519.5.2.1.6279.6001.564534197011295112247542153557
+757,1.3.6.1.4.1.14519.5.2.1.6279.6001.566816709786169715745131047975
+758,1.3.6.1.4.1.14519.5.2.1.6279.6001.569096986145782511000054443951
+759,1.3.6.1.4.1.14519.5.2.1.6279.6001.584871944187559733312703328980
+760,1.3.6.1.4.1.14519.5.2.1.6279.6001.592821488053137951302246128864
+761,1.3.6.1.4.1.14519.5.2.1.6279.6001.596908385953413160131451426904
+762,1.3.6.1.4.1.14519.5.2.1.6279.6001.603126300703296693942875967838
+763,1.3.6.1.4.1.14519.5.2.1.6279.6001.603166427542096384265514998412
+764,1.3.6.1.4.1.14519.5.2.1.6279.6001.608029415915051219877530734559
+765,1.3.6.1.4.1.14519.5.2.1.6279.6001.613212850444255764524630781782
+766,1.3.6.1.4.1.14519.5.2.1.6279.6001.614147706162329660656328811671
+767,1.3.6.1.4.1.14519.5.2.1.6279.6001.616033753016904899083676284739
+768,1.3.6.1.4.1.14519.5.2.1.6279.6001.618434772073433276874225174904
+769,1.3.6.1.4.1.14519.5.2.1.6279.6001.619372068417051974713149104919
+770,1.3.6.1.4.1.14519.5.2.1.6279.6001.621916089407825046337959219998
+771,1.3.6.1.4.1.14519.5.2.1.6279.6001.622243923620914676263059698181
+772,1.3.6.1.4.1.14519.5.2.1.6279.6001.624425075947752229712087113746
+773,1.3.6.1.4.1.14519.5.2.1.6279.6001.625270601160880745954773142570
+774,1.3.6.1.4.1.14519.5.2.1.6279.6001.627998298349675613581885874395
+775,1.3.6.1.4.1.14519.5.2.1.6279.6001.631047517458234322522264161877
+776,1.3.6.1.4.1.14519.5.2.1.6279.6001.640729228179368154416184318668
+777,1.3.6.1.4.1.14519.5.2.1.6279.6001.652347820272212119124022644822
+778,1.3.6.1.4.1.14519.5.2.1.6279.6001.655242448149322898770987310561
+779,1.3.6.1.4.1.14519.5.2.1.6279.6001.657775098760536289051744981056
+780,1.3.6.1.4.1.14519.5.2.1.6279.6001.658611160253017715059194304729
+781,1.3.6.1.4.1.14519.5.2.1.6279.6001.663019255629770796363333877035
+782,1.3.6.1.4.1.14519.5.2.1.6279.6001.664409965623578819357819577077
+783,1.3.6.1.4.1.14519.5.2.1.6279.6001.664989286137882319237192185951
+784,1.3.6.1.4.1.14519.5.2.1.6279.6001.669435869708883155232318480131
+785,1.3.6.1.4.1.14519.5.2.1.6279.6001.669518152156802508672627785405
+786,1.3.6.1.4.1.14519.5.2.1.6279.6001.670107649586205629860363487713
+787,1.3.6.1.4.1.14519.5.2.1.6279.6001.671278273674156798801285503514
+788,1.3.6.1.4.1.14519.5.2.1.6279.6001.674809958213117379592437424616
+789,1.3.6.1.4.1.14519.5.2.1.6279.6001.675543413149938600000570588203
+790,1.3.6.1.4.1.14519.5.2.1.6279.6001.686193079844756926365065559979
+791,1.3.6.1.4.1.14519.5.2.1.6279.6001.690929968028676628605553365896
+792,1.3.6.1.4.1.14519.5.2.1.6279.6001.692598144815688523679745963696
+793,1.3.6.1.4.1.14519.5.2.1.6279.6001.693480911433291675609148051914
+794,1.3.6.1.4.1.14519.5.2.1.6279.6001.701514276942509393419164159551
+795,1.3.6.1.4.1.14519.5.2.1.6279.6001.707218743153927597786179232739
+796,1.3.6.1.4.1.14519.5.2.1.6279.6001.710845873679853791427022019413
+797,1.3.6.1.4.1.14519.5.2.1.6279.6001.712472578497712558367294720243
+798,1.3.6.1.4.1.14519.5.2.1.6279.6001.716498695101447665580610403574
+799,1.3.6.1.4.1.14519.5.2.1.6279.6001.724251104254976962355686318345
+800,1.3.6.1.4.1.14519.5.2.1.6279.6001.724562063158320418413995627171
+801,1.3.6.1.4.1.14519.5.2.1.6279.6001.725023183844147505748475581290
+802,1.3.6.1.4.1.14519.5.2.1.6279.6001.725236073737175770730904408416
+803,1.3.6.1.4.1.14519.5.2.1.6279.6001.733642690503782454656013446707
+804,1.3.6.1.4.1.14519.5.2.1.6279.6001.741709061958490690246385302477
+805,1.3.6.1.4.1.14519.5.2.1.6279.6001.743969234977916254223533321294
+806,1.3.6.1.4.1.14519.5.2.1.6279.6001.745109871503276594185453478952
+807,1.3.6.1.4.1.14519.5.2.1.6279.6001.747803439040091794717626507402
+808,1.3.6.1.4.1.14519.5.2.1.6279.6001.749871569713868632259874663577
+809,1.3.6.1.4.1.14519.5.2.1.6279.6001.750792629100457382099842515038
+810,1.3.6.1.4.1.14519.5.2.1.6279.6001.752756872840730509471096155114
+811,1.3.6.1.4.1.14519.5.2.1.6279.6001.756684168227383088294595834066
+812,1.3.6.1.4.1.14519.5.2.1.6279.6001.765459236550358748053283544075
+813,1.3.6.1.4.1.14519.5.2.1.6279.6001.765930210026773090100532964804
+814,1.3.6.1.4.1.14519.5.2.1.6279.6001.766881513533845439335142582269
+815,1.3.6.1.4.1.14519.5.2.1.6279.6001.768276876111112560631432843476
+816,1.3.6.1.4.1.14519.5.2.1.6279.6001.771741891125176943862272696845
+817,1.3.6.1.4.1.14519.5.2.1.6279.6001.771831598853841017505646275338
+818,1.3.6.1.4.1.14519.5.2.1.6279.6001.774060103415303828812229821954
+819,1.3.6.1.4.1.14519.5.2.1.6279.6001.776429308535398795601496131524
+820,1.3.6.1.4.1.14519.5.2.1.6279.6001.776800177074349870648765614630
+821,1.3.6.1.4.1.14519.5.2.1.6279.6001.779493719385047675154892222907
+822,1.3.6.1.4.1.14519.5.2.1.6279.6001.780558315515979171413904604168
+823,1.3.6.1.4.1.14519.5.2.1.6279.6001.792381786708289670758399079830
+824,1.3.6.1.4.1.14519.5.2.1.6279.6001.797637294244261543517154417124
+825,1.3.6.1.4.1.14519.5.2.1.6279.6001.799582546798528864710752164515
+826,1.3.6.1.4.1.14519.5.2.1.6279.6001.801945620899034889998809817499
+827,1.3.6.1.4.1.14519.5.2.1.6279.6001.802595762867498341201607992711
+828,1.3.6.1.4.1.14519.5.2.1.6279.6001.803808126682275425758092691689
+829,1.3.6.1.4.1.14519.5.2.1.6279.6001.803987517543436570820681016103
+830,1.3.6.1.4.1.14519.5.2.1.6279.6001.805925269324902055566754756843
+831,1.3.6.1.4.1.14519.5.2.1.6279.6001.811825890493256320617655474043
+832,1.3.6.1.4.1.14519.5.2.1.6279.6001.814122498113547115932318256859
+833,1.3.6.1.4.1.14519.5.2.1.6279.6001.822128649427327893802314908658
+834,1.3.6.1.4.1.14519.5.2.1.6279.6001.826812708000318290301835871780
+835,1.3.6.1.4.1.14519.5.2.1.6279.6001.826829446346820089862659555750
+836,1.3.6.1.4.1.14519.5.2.1.6279.6001.832260670372728970918746541371
+837,1.3.6.1.4.1.14519.5.2.1.6279.6001.837810280808122125183730411210
+838,1.3.6.1.4.1.14519.5.2.1.6279.6001.842317928015463083368074520378
+839,1.3.6.1.4.1.14519.5.2.1.6279.6001.842980983137518332429408284002
+840,1.3.6.1.4.1.14519.5.2.1.6279.6001.850739282072340578344345230132
+841,1.3.6.1.4.1.14519.5.2.1.6279.6001.855232435861303786204450738044
+842,1.3.6.1.4.1.14519.5.2.1.6279.6001.861997885565255340442123234170
+843,1.3.6.1.4.1.14519.5.2.1.6279.6001.866845763956586959109892274084
+844,1.3.6.1.4.1.14519.5.2.1.6279.6001.868211851413924881662621747734
+845,1.3.6.1.4.1.14519.5.2.1.6279.6001.877026508860018521147620598474
+846,1.3.6.1.4.1.14519.5.2.1.6279.6001.882070241245008756731854510592
+847,1.3.6.1.4.1.14519.5.2.1.6279.6001.885168397833922082085837240429
+848,1.3.6.1.4.1.14519.5.2.1.6279.6001.885292267869246639232975687131
+849,1.3.6.1.4.1.14519.5.2.1.6279.6001.888291896309937415860209787179
+850,1.3.6.1.4.1.14519.5.2.1.6279.6001.888615810685807330497715730842
+851,1.3.6.1.4.1.14519.5.2.1.6279.6001.892375496445736188832556446335
+852,1.3.6.1.4.1.14519.5.2.1.6279.6001.897161587681142256575045076919
+853,1.3.6.1.4.1.14519.5.2.1.6279.6001.897279226481700053115245043064
+854,1.3.6.1.4.1.14519.5.2.1.6279.6001.897684031374557757145405000951
+855,1.3.6.1.4.1.14519.5.2.1.6279.6001.898642529028521482602829374444
+856,1.3.6.1.4.1.14519.5.2.1.6279.6001.900182736599353600185270496549
+857,1.3.6.1.4.1.14519.5.2.1.6279.6001.905371958588660410240398317235
+858,1.3.6.1.4.1.14519.5.2.1.6279.6001.908250781706513856628130123235
+859,1.3.6.1.4.1.14519.5.2.1.6279.6001.910435939545691201820711078950
+860,1.3.6.1.4.1.14519.5.2.1.6279.6001.910607280658963002048724648683
+861,1.3.6.1.4.1.14519.5.2.1.6279.6001.910757789941076242457816491305
+862,1.3.6.1.4.1.14519.5.2.1.6279.6001.922852847124879997825997808179
+863,1.3.6.1.4.1.14519.5.2.1.6279.6001.927394449308471452920270961822
+864,1.3.6.1.4.1.14519.5.2.1.6279.6001.931383239747372227838946053237
+865,1.3.6.1.4.1.14519.5.2.1.6279.6001.935683764293840351008008793409
+866,1.3.6.1.4.1.14519.5.2.1.6279.6001.939152384493874708850321969356
+867,1.3.6.1.4.1.14519.5.2.1.6279.6001.939216568327879462530496768794
+868,1.3.6.1.4.1.14519.5.2.1.6279.6001.943403138251347598519939390311
+869,1.3.6.1.4.1.14519.5.2.1.6279.6001.944888107209008719031293531091
+870,1.3.6.1.4.1.14519.5.2.1.6279.6001.946129570505893110165820050204
+871,1.3.6.1.4.1.14519.5.2.1.6279.6001.948414623428298219623354433437
+872,1.3.6.1.4.1.14519.5.2.1.6279.6001.952265563663939823135367733681
+873,1.3.6.1.4.1.14519.5.2.1.6279.6001.955688628308192728558382581802
+874,1.3.6.1.4.1.14519.5.2.1.6279.6001.957384617596077920906744920611
+875,1.3.6.1.4.1.14519.5.2.1.6279.6001.961063442349005937536597225349
+876,1.3.6.1.4.1.14519.5.2.1.6279.6001.964952370561266624992539111877
+877,1.3.6.1.4.1.14519.5.2.1.6279.6001.965620538050807352935663552285
+878,1.3.6.1.4.1.14519.5.2.1.6279.6001.969607480572818589276327766720
+879,1.3.6.1.4.1.14519.5.2.1.6279.6001.970264865033574190975654369557
+880,1.3.6.1.4.1.14519.5.2.1.6279.6001.970428941353693253759289796610
+881,1.3.6.1.4.1.14519.5.2.1.6279.6001.975254950136384517744116790879
+882,1.3.6.1.4.1.14519.5.2.1.6279.6001.975426625618184773401026809852
+883,1.3.6.1.4.1.14519.5.2.1.6279.6001.979083010707182900091062408058
+884,1.3.6.1.4.1.14519.5.2.1.6279.6001.980362852713685276785310240144
+885,1.3.6.1.4.1.14519.5.2.1.6279.6001.986011151772797848993829243183
+886,1.3.6.1.4.1.14519.5.2.1.6279.6001.994459772950022352718462251777
+887,1.3.6.1.4.1.14519.5.2.1.6279.6001.997611074084993415992563148335
diff --git a/training/detector/layers.py b/training/detector/layers.py
new file mode 100644
index 0000000..939b7be
--- /dev/null
+++ b/training/detector/layers.py
@@ -0,0 +1,359 @@
+import numpy as np
+
+import torch
+from torch import nn
+import math
+
+class PostRes2d(nn.Module):
+ def __init__(self, n_in, n_out, stride = 1):
+ super(PostRes2d, self).__init__()
+ self.conv1 = nn.Conv2d(n_in, n_out, kernel_size = 3, stride = stride, padding = 1)
+ self.bn1 = nn.BatchNorm2d(n_out)
+ self.relu = nn.ReLU(inplace = True)
+ self.conv2 = nn.Conv2d(n_out, n_out, kernel_size = 3, padding = 1)
+ self.bn2 = nn.BatchNorm2d(n_out)
+
+ if stride != 1 or n_out != n_in:
+ self.shortcut = nn.Sequential(
+ nn.Conv2d(n_in, n_out, kernel_size = 1, stride = stride),
+ nn.BatchNorm2d(n_out))
+ else:
+ self.shortcut = None
+
+ def forward(self, x):
+ residual = x
+ if self.shortcut is not None:
+ residual = self.shortcut(x)
+ out = self.conv1(x)
+ out = self.bn1(out)
+ out = self.relu(out)
+ out = self.conv2(out)
+ out = self.bn2(out)
+
+ out += residual
+ out = self.relu(out)
+ return out
+
+class PostRes(nn.Module):
+ def __init__(self, n_in, n_out, stride = 1):
+ super(PostRes, self).__init__()
+ self.conv1 = nn.Conv3d(n_in, n_out, kernel_size = 3, stride = stride, padding = 1)
+ self.bn1 = nn.BatchNorm3d(n_out)
+ self.relu = nn.ReLU(inplace = True)
+ self.conv2 = nn.Conv3d(n_out, n_out, kernel_size = 3, padding = 1)
+ self.bn2 = nn.BatchNorm3d(n_out)
+
+ if stride != 1 or n_out != n_in:
+ self.shortcut = nn.Sequential(
+ nn.Conv3d(n_in, n_out, kernel_size = 1, stride = stride),
+ nn.BatchNorm3d(n_out))
+ else:
+ self.shortcut = None
+
+ def forward(self, x):
+ residual = x
+ if self.shortcut is not None:
+ residual = self.shortcut(x)
+ out = self.conv1(x)
+ out = self.bn1(out)
+ out = self.relu(out)
+ out = self.conv2(out)
+ out = self.bn2(out)
+
+ out += residual
+ out = self.relu(out)
+ return out
+
+class Rec3(nn.Module):
+ def __init__(self, n0, n1, n2, n3, p = 0.0, integrate = True):
+ super(Rec3, self).__init__()
+
+ self.block01 = nn.Sequential(
+ nn.Conv3d(n0, n1, kernel_size = 3, stride = 2, padding = 1),
+ nn.BatchNorm3d(n1),
+ nn.ReLU(inplace = True),
+ nn.Conv3d(n1, n1, kernel_size = 3, padding = 1),
+ nn.BatchNorm3d(n1))
+
+ self.block11 = nn.Sequential(
+ nn.Conv3d(n1, n1, kernel_size = 3, padding = 1),
+ nn.BatchNorm3d(n1),
+ nn.ReLU(inplace = True),
+ nn.Conv3d(n1, n1, kernel_size = 3, padding = 1),
+ nn.BatchNorm3d(n1))
+
+ self.block21 = nn.Sequential(
+ nn.ConvTranspose3d(n2, n1, kernel_size = 2, stride = 2),
+ nn.BatchNorm3d(n1),
+ nn.ReLU(inplace = True),
+ nn.Conv3d(n1, n1, kernel_size = 3, padding = 1),
+ nn.BatchNorm3d(n1))
+
+ self.block12 = nn.Sequential(
+ nn.Conv3d(n1, n2, kernel_size = 3, stride = 2, padding = 1),
+ nn.BatchNorm3d(n2),
+ nn.ReLU(inplace = True),
+ nn.Conv3d(n2, n2, kernel_size = 3, padding = 1),
+ nn.BatchNorm3d(n2))
+
+ self.block22 = nn.Sequential(
+ nn.Conv3d(n2, n2, kernel_size = 3, padding = 1),
+ nn.BatchNorm3d(n2),
+ nn.ReLU(inplace = True),
+ nn.Conv3d(n2, n2, kernel_size = 3, padding = 1),
+ nn.BatchNorm3d(n2))
+
+ self.block32 = nn.Sequential(
+ nn.ConvTranspose3d(n3, n2, kernel_size = 2, stride = 2),
+ nn.BatchNorm3d(n2),
+ nn.ReLU(inplace = True),
+ nn.Conv3d(n2, n2, kernel_size = 3, padding = 1),
+ nn.BatchNorm3d(n2))
+
+ self.block23 = nn.Sequential(
+ nn.Conv3d(n2, n3, kernel_size = 3, stride = 2, padding = 1),
+ nn.BatchNorm3d(n3),
+ nn.ReLU(inplace = True),
+ nn.Conv3d(n3, n3, kernel_size = 3, padding = 1),
+ nn.BatchNorm3d(n3))
+
+ self.block33 = nn.Sequential(
+ nn.Conv3d(n3, n3, kernel_size = 3, padding = 1),
+ nn.BatchNorm3d(n3),
+ nn.ReLU(inplace = True),
+ nn.Conv3d(n3, n3, kernel_size = 3, padding = 1),
+ nn.BatchNorm3d(n3))
+
+ self.relu = nn.ReLU(inplace = True)
+ self.p = p
+ self.integrate = integrate
+
+ def forward(self, x0, x1, x2, x3):
+ if self.p > 0 and self.training:
+ coef = torch.bernoulli((1.0 - self.p) * torch.ones(8))
+ out1 = coef[0] * self.block01(x0) + coef[1] * self.block11(x1) + coef[2] * self.block21(x2)
+ out2 = coef[3] * self.block12(x1) + coef[4] * self.block22(x2) + coef[5] * self.block32(x3)
+ out3 = coef[6] * self.block23(x2) + coef[7] * self.block33(x3)
+ else:
+ out1 = (1 - self.p) * (self.block01(x0) + self.block11(x1) + self.block21(x2))
+ out2 = (1 - self.p) * (self.block12(x1) + self.block22(x2) + self.block32(x3))
+ out3 = (1 - self.p) * (self.block23(x2) + self.block33(x3))
+
+ if self.integrate:
+ out1 += x1
+ out2 += x2
+ out3 += x3
+
+ return x0, self.relu(out1), self.relu(out2), self.relu(out3)
+
+def hard_mining(neg_output, neg_labels, num_hard):
+ _, idcs = torch.topk(neg_output, min(num_hard, len(neg_output)))
+ neg_output = torch.index_select(neg_output, 0, idcs)
+ neg_labels = torch.index_select(neg_labels, 0, idcs)
+ return neg_output, neg_labels
+
+class Loss(nn.Module):
+ def __init__(self, num_hard = 0):
+ super(Loss, self).__init__()
+ self.sigmoid = nn.Sigmoid()
+ self.classify_loss = nn.BCELoss()
+ self.regress_loss = nn.SmoothL1Loss()
+ self.num_hard = num_hard
+
+ def forward(self, output, labels, train = True):
+ batch_size = labels.size(0)
+ output = output.view(-1, 5)
+ labels = labels.view(-1, 5)
+
+ pos_idcs = labels[:, 0] > 0.5
+ pos_idcs = pos_idcs.unsqueeze(1).expand(pos_idcs.size(0), 5)
+ pos_output = output[pos_idcs].view(-1, 5)
+ pos_labels = labels[pos_idcs].view(-1, 5)
+
+ neg_idcs = labels[:, 0] < -0.5
+ neg_output = output[:, 0][neg_idcs]
+ neg_labels = labels[:, 0][neg_idcs]
+
+ if self.num_hard > 0 and train:
+ neg_output, neg_labels = hard_mining(neg_output, neg_labels, self.num_hard * batch_size)
+ neg_prob = self.sigmoid(neg_output)
+
+ #classify_loss = self.classify_loss(
+ # torch.cat((pos_prob, neg_prob), 0),
+ # torch.cat((pos_labels[:, 0], neg_labels + 1), 0))
+ if len(pos_output)>0:
+ pos_prob = self.sigmoid(pos_output[:, 0])
+ pz, ph, pw, pd = pos_output[:, 1], pos_output[:, 2], pos_output[:, 3], pos_output[:, 4]
+ lz, lh, lw, ld = pos_labels[:, 1], pos_labels[:, 2], pos_labels[:, 3], pos_labels[:, 4]
+
+ regress_losses = [
+ self.regress_loss(pz, lz),
+ self.regress_loss(ph, lh),
+ self.regress_loss(pw, lw),
+ self.regress_loss(pd, ld)]
+ regress_losses_data = [l.data[0] for l in regress_losses]
+ classify_loss = 0.5 * self.classify_loss(
+ pos_prob, pos_labels[:, 0]) + 0.5 * self.classify_loss(
+ neg_prob, neg_labels + 1)
+ pos_correct = (pos_prob.data >= 0.5).sum()
+ pos_total = len(pos_prob)
+
+ else:
+ regress_losses = [0,0,0,0]
+ classify_loss = 0.5 * self.classify_loss(
+ neg_prob, neg_labels + 1)
+ pos_correct = 0
+ pos_total = 0
+ regress_losses_data = [0,0,0,0]
+ classify_loss_data = classify_loss.data[0]
+
+ loss = classify_loss
+ for regress_loss in regress_losses:
+ loss += regress_loss
+
+ neg_correct = (neg_prob.data < 0.5).sum()
+ neg_total = len(neg_prob)
+
+ return [loss, classify_loss_data] + regress_losses_data + [pos_correct, pos_total, neg_correct, neg_total]
+
+class GetPBB(object):
+ def __init__(self, config):
+ self.stride = config['stride']
+ self.anchors = np.asarray(config['anchors'])
+
+ def __call__(self, output,thresh = -3, ismask=False):
+ stride = self.stride
+ anchors = self.anchors
+ output = np.copy(output)
+ offset = (float(stride) - 1) / 2
+ output_size = output.shape
+ oz = np.arange(offset, offset + stride * (output_size[0] - 1) + 1, stride)
+ oh = np.arange(offset, offset + stride * (output_size[1] - 1) + 1, stride)
+ ow = np.arange(offset, offset + stride * (output_size[2] - 1) + 1, stride)
+
+ output[:, :, :, :, 1] = oz.reshape((-1, 1, 1, 1)) + output[:, :, :, :, 1] * anchors.reshape((1, 1, 1, -1))
+ output[:, :, :, :, 2] = oh.reshape((1, -1, 1, 1)) + output[:, :, :, :, 2] * anchors.reshape((1, 1, 1, -1))
+ output[:, :, :, :, 3] = ow.reshape((1, 1, -1, 1)) + output[:, :, :, :, 3] * anchors.reshape((1, 1, 1, -1))
+ output[:, :, :, :, 4] = np.exp(output[:, :, :, :, 4]) * anchors.reshape((1, 1, 1, -1))
+ mask = output[..., 0] > thresh
+ xx,yy,zz,aa = np.where(mask)
+
+ output = output[xx,yy,zz,aa]
+ if ismask:
+ return output,[xx,yy,zz,aa]
+ else:
+ return output
+
+ #output = output[output[:, 0] >= self.conf_th]
+ #bboxes = nms(output, self.nms_th)
+def nms(output, nms_th):
+ if len(output) == 0:
+ return output
+
+ output = output[np.argsort(-output[:, 0])]
+ bboxes = [output[0]]
+
+ for i in np.arange(1, len(output)):
+ bbox = output[i]
+ flag = 1
+ for j in range(len(bboxes)):
+ if iou(bbox[1:5], bboxes[j][1:5]) >= nms_th:
+ flag = -1
+ break
+ if flag == 1:
+ bboxes.append(bbox)
+
+ bboxes = np.asarray(bboxes, np.float32)
+ return bboxes
+
+def iou(box0, box1):
+
+ r0 = box0[3] / 2
+ s0 = box0[:3] - r0
+ e0 = box0[:3] + r0
+
+ r1 = box1[3] / 2
+ s1 = box1[:3] - r1
+ e1 = box1[:3] + r1
+
+ overlap = []
+ for i in range(len(s0)):
+ overlap.append(max(0, min(e0[i], e1[i]) - max(s0[i], s1[i])))
+
+ intersection = overlap[0] * overlap[1] * overlap[2]
+ union = box0[3] * box0[3] * box0[3] + box1[3] * box1[3] * box1[3] - intersection
+ return intersection / union
+
+def acc(pbb, lbb, conf_th, nms_th, detect_th):
+ pbb = pbb[pbb[:, 0] >= conf_th]
+ pbb = nms(pbb, nms_th)
+
+ tp = []
+ fp = []
+ fn = []
+ l_flag = np.zeros((len(lbb),), np.int32)
+ for p in pbb:
+ flag = 0
+ bestscore = 0
+ for i, l in enumerate(lbb):
+ score = iou(p[1:5], l)
+ if score>bestscore:
+ bestscore = score
+ besti = i
+ if bestscore > detect_th:
+ flag = 1
+ if l_flag[besti] == 0:
+ l_flag[besti] = 1
+ tp.append(np.concatenate([p,[bestscore]],0))
+ else:
+ fp.append(np.concatenate([p,[bestscore]],0))
+ if flag == 0:
+ fp.append(np.concatenate([p,[bestscore]],0))
+ for i,l in enumerate(lbb):
+ if l_flag[i]==0:
+ score = []
+ for p in pbb:
+ score.append(iou(p[1:5],l))
+ if len(score)!=0:
+ bestscore = np.max(score)
+ else:
+ bestscore = 0
+ if bestscore0:
+ fn = np.concatenate([fn,tp[fn_i,:5]])
+ else:
+ fn = fn
+ if len(tp_in_topk)>0:
+ tp = tp[tp_in_topk]
+ else:
+ tp = []
+ if len(fp_in_topk)>0:
+ fp = newallp[fp_in_topk]
+ else:
+ fp = []
+ return tp, fp , fn
diff --git a/training/detector/main.py b/training/detector/main.py
new file mode 100644
index 0000000..81a31c1
--- /dev/null
+++ b/training/detector/main.py
@@ -0,0 +1,349 @@
+import argparse
+import os
+import time
+import numpy as np
+import data
+from importlib import import_module
+import shutil
+from utils import *
+import sys
+sys.path.append('../')
+from split_combine import SplitComb
+
+import torch
+from torch.nn import DataParallel
+from torch.backends import cudnn
+from torch.utils.data import DataLoader
+from torch import optim
+from torch.autograd import Variable
+from config_training import config as config_training
+
+from layers import acc
+
+parser = argparse.ArgumentParser(description='PyTorch DataBowl3 Detector')
+parser.add_argument('--model', '-m', metavar='MODEL', default='base',
+ help='model')
+parser.add_argument('-j', '--workers', default=32, type=int, metavar='N',
+ help='number of data loading workers (default: 32)')
+parser.add_argument('--epochs', default=100, type=int, metavar='N',
+ help='number of total epochs to run')
+parser.add_argument('--start-epoch', default=0, type=int, metavar='N',
+ help='manual epoch number (useful on restarts)')
+parser.add_argument('-b', '--batch-size', default=16, type=int,
+ metavar='N', help='mini-batch size (default: 16)')
+parser.add_argument('--lr', '--learning-rate', default=0.01, type=float,
+ metavar='LR', help='initial learning rate')
+parser.add_argument('--momentum', default=0.9, type=float, metavar='M',
+ help='momentum')
+parser.add_argument('--weight-decay', '--wd', default=1e-4, type=float,
+ metavar='W', help='weight decay (default: 1e-4)')
+parser.add_argument('--save-freq', default='10', type=int, metavar='S',
+ help='save frequency')
+parser.add_argument('--resume', default='', type=str, metavar='PATH',
+ help='path to latest checkpoint (default: none)')
+parser.add_argument('--save-dir', default='', type=str, metavar='SAVE',
+ help='directory to save checkpoint (default: none)')
+parser.add_argument('--test', default=0, type=int, metavar='TEST',
+ help='1 do test evaluation, 0 not')
+parser.add_argument('--split', default=8, type=int, metavar='SPLIT',
+ help='In the test phase, split the image to 8 parts')
+parser.add_argument('--gpu', default='all', type=str, metavar='N',
+ help='use gpu')
+parser.add_argument('--n_test', default=8, type=int, metavar='N',
+ help='number of gpu for test')
+
+def main():
+ global args
+ args = parser.parse_args()
+
+
+ torch.manual_seed(0)
+ torch.cuda.set_device(0)
+
+ model = import_module(args.model)
+ config, net, loss, get_pbb = model.get_model()
+ start_epoch = args.start_epoch
+ save_dir = args.save_dir
+
+ if args.resume:
+ checkpoint = torch.load(args.resume)
+ if start_epoch == 0:
+ start_epoch = checkpoint['epoch'] + 1
+ if not save_dir:
+ save_dir = checkpoint['save_dir']
+ else:
+ save_dir = os.path.join('results',save_dir)
+ net.load_state_dict(checkpoint['state_dict'])
+ else:
+ if start_epoch == 0:
+ start_epoch = 1
+ if not save_dir:
+ exp_id = time.strftime('%Y%m%d-%H%M%S', time.localtime())
+ save_dir = os.path.join('results', args.model + '-' + exp_id)
+ else:
+ save_dir = os.path.join('results',save_dir)
+
+ if not os.path.exists(save_dir):
+ os.makedirs(save_dir)
+ logfile = os.path.join(save_dir,'log')
+ if args.test!=1:
+ sys.stdout = Logger(logfile)
+ pyfiles = [f for f in os.listdir('./') if f.endswith('.py')]
+ for f in pyfiles:
+ shutil.copy(f,os.path.join(save_dir,f))
+ n_gpu = setgpu(args.gpu)
+ args.n_gpu = n_gpu
+ net = net.cuda()
+ loss = loss.cuda()
+ cudnn.benchmark = True
+ net = DataParallel(net)
+ datadir = config_training['preprocess_result_path']
+
+ if args.test == 1:
+ margin = 32
+ sidelen = 144
+
+ split_comber = SplitComb(sidelen,config['max_stride'],config['stride'],margin,config['pad_value'])
+ dataset = data.DataBowl3Detector(
+ datadir,
+ 'full.npy',
+ config,
+ phase='test',
+ split_comber=split_comber)
+ test_loader = DataLoader(
+ dataset,
+ batch_size = 1,
+ shuffle = False,
+ num_workers = args.workers,
+ collate_fn = data.collate,
+ pin_memory=False)
+
+ test(test_loader, net, get_pbb, save_dir,config)
+ return
+
+ #net = DataParallel(net)
+
+ dataset = data.DataBowl3Detector(
+ datadir,
+ 'kaggleluna_full.npy',
+ config,
+ phase = 'train')
+ train_loader = DataLoader(
+ dataset,
+ batch_size = args.batch_size,
+ shuffle = True,
+ num_workers = args.workers,
+ pin_memory=True)
+
+ dataset = data.DataBowl3Detector(
+ datadir,
+ 'valsplit.npy',
+ config,
+ phase = 'val')
+ val_loader = DataLoader(
+ dataset,
+ batch_size = args.batch_size,
+ shuffle = False,
+ num_workers = args.workers,
+ pin_memory=True)
+
+ optimizer = torch.optim.SGD(
+ net.parameters(),
+ args.lr,
+ momentum = 0.9,
+ weight_decay = args.weight_decay)
+
+ def get_lr(epoch):
+ if epoch <= args.epochs * 0.5:
+ lr = args.lr
+ elif epoch <= args.epochs * 0.8:
+ lr = 0.1 * args.lr
+ else:
+ lr = 0.01 * args.lr
+ return lr
+
+
+ for epoch in range(start_epoch, args.epochs + 1):
+ train(train_loader, net, loss, epoch, optimizer, get_lr, args.save_freq, save_dir)
+ validate(val_loader, net, loss)
+
+def train(data_loader, net, loss, epoch, optimizer, get_lr, save_freq, save_dir):
+ start_time = time.time()
+
+ net.train()
+ lr = get_lr(epoch)
+ for param_group in optimizer.param_groups:
+ param_group['lr'] = lr
+
+ metrics = []
+ for i, (data, target, coord) in enumerate(data_loader):
+ data = Variable(data.cuda(async = True))
+ target = Variable(target.cuda(async = True))
+ coord = Variable(coord.cuda(async = True))
+
+ output = net(data, coord)
+ loss_output = loss(output, target)
+ optimizer.zero_grad()
+ loss_output[0].backward()
+ optimizer.step()
+
+ loss_output[0] = loss_output[0].data[0]
+ metrics.append(loss_output)
+
+ if epoch % args.save_freq == 0:
+ state_dict = net.module.state_dict()
+ for key in state_dict.keys():
+ state_dict[key] = state_dict[key].cpu()
+
+ torch.save({
+ 'epoch': epoch,
+ 'save_dir': save_dir,
+ 'state_dict': state_dict,
+ 'args': args},
+ os.path.join(save_dir, '%03d.ckpt' % epoch))
+
+ end_time = time.time()
+
+ metrics = np.asarray(metrics, np.float32)
+ print('Epoch %03d (lr %.5f)' % (epoch, lr))
+ print('Train: tpr %3.2f, tnr %3.2f, total pos %d, total neg %d, time %3.2f' % (
+ 100.0 * np.sum(metrics[:, 6]) / np.sum(metrics[:, 7]),
+ 100.0 * np.sum(metrics[:, 8]) / np.sum(metrics[:, 9]),
+ np.sum(metrics[:, 7]),
+ np.sum(metrics[:, 9]),
+ end_time - start_time))
+ print('loss %2.4f, classify loss %2.4f, regress loss %2.4f, %2.4f, %2.4f, %2.4f' % (
+ np.mean(metrics[:, 0]),
+ np.mean(metrics[:, 1]),
+ np.mean(metrics[:, 2]),
+ np.mean(metrics[:, 3]),
+ np.mean(metrics[:, 4]),
+ np.mean(metrics[:, 5])))
+ print
+
+def validate(data_loader, net, loss):
+ start_time = time.time()
+
+ net.eval()
+
+ metrics = []
+ for i, (data, target, coord) in enumerate(data_loader):
+ data = Variable(data.cuda(async = True), volatile = True)
+ target = Variable(target.cuda(async = True), volatile = True)
+ coord = Variable(coord.cuda(async = True), volatile = True)
+
+ output = net(data, coord)
+ loss_output = loss(output, target, train = False)
+
+ loss_output[0] = loss_output[0].data[0]
+ metrics.append(loss_output)
+ end_time = time.time()
+
+ metrics = np.asarray(metrics, np.float32)
+ print('Validation: tpr %3.2f, tnr %3.8f, total pos %d, total neg %d, time %3.2f' % (
+ 100.0 * np.sum(metrics[:, 6]) / np.sum(metrics[:, 7]),
+ 100.0 * np.sum(metrics[:, 8]) / np.sum(metrics[:, 9]),
+ np.sum(metrics[:, 7]),
+ np.sum(metrics[:, 9]),
+ end_time - start_time))
+ print('loss %2.4f, classify loss %2.4f, regress loss %2.4f, %2.4f, %2.4f, %2.4f' % (
+ np.mean(metrics[:, 0]),
+ np.mean(metrics[:, 1]),
+ np.mean(metrics[:, 2]),
+ np.mean(metrics[:, 3]),
+ np.mean(metrics[:, 4]),
+ np.mean(metrics[:, 5])))
+ print
+ print
+
+def test(data_loader, net, get_pbb, save_dir, config):
+ start_time = time.time()
+ save_dir = os.path.join(save_dir,'bbox')
+ if not os.path.exists(save_dir):
+ os.makedirs(save_dir)
+ print(save_dir)
+ net.eval()
+ namelist = []
+ split_comber = data_loader.dataset.split_comber
+ for i_name, (data, target, coord, nzhw) in enumerate(data_loader):
+ s = time.time()
+ target = [np.asarray(t, np.float32) for t in target]
+ lbb = target[0]
+ nzhw = nzhw[0]
+ name = data_loader.dataset.filenames[i_name].split('-')[0].split('/')[-1].split('_clean')[0]
+ data = data[0][0]
+ coord = coord[0][0]
+ isfeat = False
+ if 'output_feature' in config:
+ if config['output_feature']:
+ isfeat = True
+ n_per_run = args.n_test
+ print(data.size())
+ splitlist = range(0,len(data)+1,n_per_run)
+ if splitlist[-1]!=len(data):
+ splitlist.append(len(data))
+ outputlist = []
+ featurelist = []
+
+ for i in range(len(splitlist)-1):
+ input = Variable(data[splitlist[i]:splitlist[i+1]], volatile = True).cuda()
+ inputcoord = Variable(coord[splitlist[i]:splitlist[i+1]], volatile = True).cuda()
+ if isfeat:
+ output,feature = net(input,inputcoord)
+ featurelist.append(feature.data.cpu().numpy())
+ else:
+ output = net(input,inputcoord)
+ outputlist.append(output.data.cpu().numpy())
+ output = np.concatenate(outputlist,0)
+ output = split_comber.combine(output,nzhw=nzhw)
+ if isfeat:
+ feature = np.concatenate(featurelist,0).transpose([0,2,3,4,1])[:,:,:,:,:,np.newaxis]
+ feature = split_comber.combine(feature,sidelen)[...,0]
+
+ thresh = -3
+ pbb,mask = get_pbb(output,thresh,ismask=True)
+ if isfeat:
+ feature_selected = feature[mask[0],mask[1],mask[2]]
+ np.save(os.path.join(save_dir, name+'_feature.npy'), feature_selected)
+ #tp,fp,fn,_ = acc(pbb,lbb,0,0.1,0.1)
+ #print([len(tp),len(fp),len(fn)])
+ print([i_name,name])
+ e = time.time()
+ np.save(os.path.join(save_dir, name+'_pbb.npy'), pbb)
+ np.save(os.path.join(save_dir, name+'_lbb.npy'), lbb)
+ np.save(os.path.join(save_dir, 'namelist.npy'), namelist)
+ end_time = time.time()
+
+
+ print('elapsed time is %3.2f seconds' % (end_time - start_time))
+ print
+ print
+
+def singletest(data,net,config,splitfun,combinefun,n_per_run,margin = 64,isfeat=False):
+ z, h, w = data.size(2), data.size(3), data.size(4)
+ print(data.size())
+ data = splitfun(data,config['max_stride'],margin)
+ data = Variable(data.cuda(async = True), volatile = True,requires_grad=False)
+ splitlist = range(0,args.split+1,n_per_run)
+ outputlist = []
+ featurelist = []
+ for i in range(len(splitlist)-1):
+ if isfeat:
+ output,feature = net(data[splitlist[i]:splitlist[i+1]])
+ featurelist.append(feature)
+ else:
+ output = net(data[splitlist[i]:splitlist[i+1]])
+ output = output.data.cpu().numpy()
+ outputlist.append(output)
+
+ output = np.concatenate(outputlist,0)
+ output = combinefun(output, z / config['stride'], h / config['stride'], w / config['stride'])
+ if isfeat:
+ feature = np.concatenate(featurelist,0).transpose([0,2,3,4,1])
+ feature = combinefun(feature, z / config['stride'], h / config['stride'], w / config['stride'])
+ return output,feature
+ else:
+ return output
+if __name__ == '__main__':
+ main()
+
diff --git a/training/detector/res18.py b/training/detector/res18.py
new file mode 100644
index 0000000..5e133f5
--- /dev/null
+++ b/training/detector/res18.py
@@ -0,0 +1,126 @@
+import torch
+from torch import nn
+from layers import *
+
+config = {}
+config['anchors'] = [ 10.0, 30.0, 60.]
+config['chanel'] = 1
+config['crop_size'] = [128, 128, 128]
+config['stride'] = 4
+config['max_stride'] = 16
+config['num_neg'] = 800
+config['th_neg'] = 0.02
+config['th_pos_train'] = 0.5
+config['th_pos_val'] = 1
+config['num_hard'] = 2
+config['bound_size'] = 12
+config['reso'] = 1
+config['sizelim'] = 6. #mm
+config['sizelim2'] = 30
+config['sizelim3'] = 40
+config['aug_scale'] = True
+config['r_rand_crop'] = 0.3
+config['pad_value'] = 170
+config['augtype'] = {'flip':True,'swap':False,'scale':True,'rotate':False}
+config['blacklist'] = ['868b024d9fa388b7ddab12ec1c06af38','990fbe3f0a1b53878669967b9afd1441','adc3bbc63d40f8761c59be10f1e504c3']
+
+#config['blacklist'] = ['868b024d9fa388b7ddab12ec1c06af38','d92998a73d4654a442e6d6ba15bbb827','990fbe3f0a1b53878669967b9afd1441','820245d8b211808bd18e78ff5be16fdb','adc3bbc63d40f8761c59be10f1e504c3',
+# '417','077','188','876','057','087','130','468']
+
+class Net(nn.Module):
+ def __init__(self):
+ super(Net, self).__init__()
+ # The first few layers consumes the most memory, so use simple convolution to save memory.
+ # Call these layers preBlock, i.e., before the residual blocks of later layers.
+ self.preBlock = nn.Sequential(
+ nn.Conv3d(1, 24, kernel_size = 3, padding = 1),
+ nn.BatchNorm3d(24),
+ nn.ReLU(inplace = True),
+ nn.Conv3d(24, 24, kernel_size = 3, padding = 1),
+ nn.BatchNorm3d(24),
+ nn.ReLU(inplace = True))
+
+ # 3 poolings, each pooling downsamples the feature map by a factor 2.
+ # 3 groups of blocks. The first block of each group has one pooling.
+ num_blocks_forw = [2,2,3,3]
+ num_blocks_back = [3,3]
+ self.featureNum_forw = [24,32,64,64,64]
+ self.featureNum_back = [128,64,64]
+ for i in range(len(num_blocks_forw)):
+ blocks = []
+ for j in range(num_blocks_forw[i]):
+ if j == 0:
+ blocks.append(PostRes(self.featureNum_forw[i], self.featureNum_forw[i+1]))
+ else:
+ blocks.append(PostRes(self.featureNum_forw[i+1], self.featureNum_forw[i+1]))
+ setattr(self, 'forw' + str(i + 1), nn.Sequential(*blocks))
+
+
+ for i in range(len(num_blocks_back)):
+ blocks = []
+ for j in range(num_blocks_back[i]):
+ if j == 0:
+ if i==0:
+ addition = 3
+ else:
+ addition = 0
+ blocks.append(PostRes(self.featureNum_back[i+1]+self.featureNum_forw[i+2]+addition, self.featureNum_back[i]))
+ else:
+ blocks.append(PostRes(self.featureNum_back[i], self.featureNum_back[i]))
+ setattr(self, 'back' + str(i + 2), nn.Sequential(*blocks))
+
+ self.maxpool1 = nn.MaxPool3d(kernel_size=2,stride=2,return_indices =True)
+ self.maxpool2 = nn.MaxPool3d(kernel_size=2,stride=2,return_indices =True)
+ self.maxpool3 = nn.MaxPool3d(kernel_size=2,stride=2,return_indices =True)
+ self.maxpool4 = nn.MaxPool3d(kernel_size=2,stride=2,return_indices =True)
+ self.unmaxpool1 = nn.MaxUnpool3d(kernel_size=2,stride=2)
+ self.unmaxpool2 = nn.MaxUnpool3d(kernel_size=2,stride=2)
+
+ self.path1 = nn.Sequential(
+ nn.ConvTranspose3d(64, 64, kernel_size = 2, stride = 2),
+ nn.BatchNorm3d(64),
+ nn.ReLU(inplace = True))
+ self.path2 = nn.Sequential(
+ nn.ConvTranspose3d(64, 64, kernel_size = 2, stride = 2),
+ nn.BatchNorm3d(64),
+ nn.ReLU(inplace = True))
+ self.drop = nn.Dropout3d(p = 0.5, inplace = False)
+ self.output = nn.Sequential(nn.Conv3d(self.featureNum_back[0], 64, kernel_size = 1),
+ nn.ReLU(),
+ #nn.Dropout3d(p = 0.3),
+ nn.Conv3d(64, 5 * len(config['anchors']), kernel_size = 1))
+
+ def forward(self, x, coord):
+ out = self.preBlock(x)#16
+ out_pool,indices0 = self.maxpool1(out)
+ out1 = self.forw1(out_pool)#32
+ out1_pool,indices1 = self.maxpool2(out1)
+ out2 = self.forw2(out1_pool)#64
+ #out2 = self.drop(out2)
+ out2_pool,indices2 = self.maxpool3(out2)
+ out3 = self.forw3(out2_pool)#96
+ out3_pool,indices3 = self.maxpool4(out3)
+ out4 = self.forw4(out3_pool)#96
+ #out4 = self.drop(out4)
+
+ rev3 = self.path1(out4)
+ comb3 = self.back3(torch.cat((rev3, out3), 1))#96+96
+ #comb3 = self.drop(comb3)
+ rev2 = self.path2(comb3)
+
+ comb2 = self.back2(torch.cat((rev2, out2,coord), 1))#64+64
+ comb2 = self.drop(comb2)
+ out = self.output(comb2)
+ size = out.size()
+ out = out.view(out.size(0), out.size(1), -1)
+ #out = out.transpose(1, 4).transpose(1, 2).transpose(2, 3).contiguous()
+ out = out.transpose(1, 2).contiguous().view(size[0], size[2], size[3], size[4], len(config['anchors']), 5)
+ #out = out.view(-1, 5)
+ return out
+
+
+def get_model():
+ net = Net()
+ loss = Loss(config['num_hard'])
+ get_pbb = GetPBB(config)
+ return config, net, loss, get_pbb
diff --git a/training/detector/res_pool.py b/training/detector/res_pool.py
new file mode 100644
index 0000000..42001d6
--- /dev/null
+++ b/training/detector/res_pool.py
@@ -0,0 +1,107 @@
+import torch
+from torch import nn
+from layers import *
+
+config = {}
+config['anchors'] = [ 10.0, 25.0, 40.0]
+config['chanel'] = 2
+config['crop_size'] = [64, 128, 128]
+config['stride'] = [2,4,4]
+config['max_stride'] = 16
+config['num_neg'] = 10
+config['th_neg'] = 0.2
+config['th_pos'] = 0.5
+config['num_hard'] = 1
+config['bound_size'] = 12
+config['reso'] = [1.5,0.75,0.75]
+config['sizelim'] = 6. #mm
+config['blacklist'] = ['868b024d9fa388b7ddab12ec1c06af38','d92998a73d4654a442e6d6ba15bbb827','990fbe3f0a1b53878669967b9afd1441','820245d8b211808bd18e78ff5be16fdb',
+ '417','077','188','876','057','087','130','468']
+
+class Net(nn.Module):
+ def __init__(self):
+ super(Net, self).__init__()
+ # The first few layers consumes the most memory, so use simple convolution to save memory.
+ # Call these layers preBlock, i.e., before the residual blocks of later layers.
+ self.preBlock = nn.Sequential(
+ nn.Conv3d(2, 16, kernel_size = 3, padding = 1),
+ nn.BatchNorm3d(16),
+ nn.ReLU(inplace = True),
+ nn.Conv3d(16, 16, kernel_size = 3, padding = 1),
+ nn.BatchNorm3d(16),
+ nn.ReLU(inplace = True))
+
+ # 3 poolings, each pooling downsamples the feature map by a factor 2.
+ # 3 groups of blocks. The first block of each group has one pooling.
+ num_blocks = [6,6,6,6]
+ n_in = [16, 32, 64,96]
+ n_out = [32, 64, 96,96]
+ for i in range(len(num_blocks)):
+ blocks = []
+ for j in range(num_blocks[i]):
+ if j == 0:
+ if i ==0:
+ blocks.append(nn.MaxPool3d(kernel_size=[1,2,2]))
+ blocks.append(PostRes(n_in[i], n_out[i]))
+ else:
+ blocks.append(nn.MaxPool3d(kernel_size=2))
+ blocks.append(PostRes(n_out[i], n_out[i]))
+ else:
+ blocks.append(PostRes(n_out[i], n_out[i]))
+ setattr(self, 'group' + str(i + 1), nn.Sequential(*blocks))
+
+ self.path1 = nn.Sequential(
+ nn.Conv3d(64, 32, kernel_size = 3, padding = 1),
+ nn.BatchNorm3d(32),
+ nn.ReLU(inplace = True))
+
+ self.path2 = nn.Sequential(
+ nn.ConvTranspose3d(96, 32, kernel_size = 2, stride = 2),
+ nn.BatchNorm3d(32),
+ nn.ReLU(inplace = True))
+
+ self.path3 = nn.Sequential(
+ nn.ConvTranspose3d(96, 32, kernel_size = 2, stride = 2),
+ nn.BatchNorm3d(32),
+ nn.ReLU(inplace = True),
+ nn.ConvTranspose3d(32, 32, kernel_size = 2, stride = 2),
+ nn.BatchNorm3d(32),
+ nn.ReLU(inplace = True))
+
+ self.combine = nn.Sequential(
+ nn.Conv3d(96, 128, kernel_size = 1),
+ nn.BatchNorm3d(128),
+ nn.ReLU(inplace = True))
+
+ self.drop = nn.Dropout3d(p = 0.5, inplace = False)
+ self.output = nn.Conv3d(128, 5 * len(config['anchors']), kernel_size = 1)
+
+ def forward(self, x):
+ x = x.view(x.size(0), 2,x.size(2), x.size(3), x.size(4))
+ out = self.preBlock(x)
+
+ out1 = self.group1(out)
+ out2 = self.group2(out1)
+ out3 = self.group3(out2)
+ out4 = self.group4(out3)
+
+ out2 = self.path1(out2)
+ out3 = self.path2(out3)
+ out4 = self.path3(out4)
+ out = torch.cat((out2, out3, out4), 1)
+
+ out = self.combine(out)
+ out = self.drop(out)
+ out = self.output(out)
+ size = out.size()
+ out = out.view(out.size(0), out.size(1), -1)
+ #out = out.transpose(1, 4).transpose(1, 2).transpose(2, 3).contiguous()
+ out = out.transpose(1, 2).contiguous().view(size[0], size[2], size[3], size[4], len(config['anchors']), 5)
+ #out = out.view(-1, 5)
+ return out
+
+def get_model():
+ net = Net()
+ loss = Loss(config['num_hard'])
+ get_pbb = GetPBB(config)
+ return config, net, loss, get_pbb
diff --git a/training/detector/results/.gitignore b/training/detector/results/.gitignore
new file mode 100644
index 0000000..76bedae
--- /dev/null
+++ b/training/detector/results/.gitignore
@@ -0,0 +1,5 @@
+# Ignore everything in this directory
+*
+# Except this file
+!.gitignore
+
diff --git a/training/detector/split_combine.py b/training/detector/split_combine.py
new file mode 100644
index 0000000..d4b5b49
--- /dev/null
+++ b/training/detector/split_combine.py
@@ -0,0 +1,100 @@
+import torch
+import numpy as np
+class SplitComb():
+ def __init__(self,side_len,max_stride,stride,margin,pad_value):
+ self.side_len = side_len
+ self.max_stride = max_stride
+ self.stride = stride
+ self.margin = margin
+ self.pad_value = pad_value
+
+ def split(self, data, side_len = None, max_stride = None, margin = None):
+ if side_len==None:
+ side_len = self.side_len
+ if max_stride == None:
+ max_stride = self.max_stride
+ if margin == None:
+ margin = self.margin
+
+ assert(side_len > margin)
+ assert(side_len % max_stride == 0)
+ assert(margin % max_stride == 0)
+
+ splits = []
+ _, z, h, w = data.shape
+
+ nz = int(np.ceil(float(z) / side_len))
+ nh = int(np.ceil(float(h) / side_len))
+ nw = int(np.ceil(float(w) / side_len))
+
+ nzhw = [nz,nh,nw]
+ self.nzhw = nzhw
+
+ pad = [ [0, 0],
+ [margin, nz * side_len - z + margin],
+ [margin, nh * side_len - h + margin],
+ [margin, nw * side_len - w + margin]]
+ data = np.pad(data, pad, 'edge')
+
+ for iz in range(nz):
+ for ih in range(nh):
+ for iw in range(nw):
+ sz = iz * side_len
+ ez = (iz + 1) * side_len + 2 * margin
+ sh = ih * side_len
+ eh = (ih + 1) * side_len + 2 * margin
+ sw = iw * side_len
+ ew = (iw + 1) * side_len + 2 * margin
+
+ split = data[np.newaxis, :, sz:ez, sh:eh, sw:ew]
+ splits.append(split)
+
+ splits = np.concatenate(splits, 0)
+ return splits,nzhw
+
+ def combine(self, output, nzhw = None, side_len=None, stride=None, margin=None):
+
+ if side_len==None:
+ side_len = self.side_len
+ if stride == None:
+ stride = self.stride
+ if margin == None:
+ margin = self.margin
+ if nzhw==None:
+ nz = self.nz
+ nh = self.nh
+ nw = self.nw
+ else:
+ nz,nh,nw = nzhw
+ assert(side_len % stride == 0)
+ assert(margin % stride == 0)
+ side_len /= stride
+ margin /= stride
+
+ splits = []
+ for i in range(len(output)):
+ splits.append(output[i])
+
+ output = -1000000 * np.ones((
+ nz * side_len,
+ nh * side_len,
+ nw * side_len,
+ splits[0].shape[3],
+ splits[0].shape[4]), np.float32)
+
+ idx = 0
+ for iz in range(nz):
+ for ih in range(nh):
+ for iw in range(nw):
+ sz = iz * side_len
+ ez = (iz + 1) * side_len
+ sh = ih * side_len
+ eh = (ih + 1) * side_len
+ sw = iw * side_len
+ ew = (iw + 1) * side_len
+
+ split = splits[idx][margin:margin + side_len, margin:margin + side_len, margin:margin + side_len]
+ output[sz:ez, sh:eh, sw:ew] = split
+ idx += 1
+
+ return output
diff --git a/training/detector/test.npy b/training/detector/test.npy
new file mode 100644
index 0000000..53d21d0
Binary files /dev/null and b/training/detector/test.npy differ
diff --git a/training/detector/utils.py b/training/detector/utils.py
new file mode 100644
index 0000000..8743c82
--- /dev/null
+++ b/training/detector/utils.py
@@ -0,0 +1,308 @@
+import sys
+import os
+import numpy as np
+import torch
+def getFreeId():
+ import pynvml
+
+ pynvml.nvmlInit()
+ def getFreeRatio(id):
+ handle = pynvml.nvmlDeviceGetHandleByIndex(id)
+ use = pynvml.nvmlDeviceGetUtilizationRates(handle)
+ ratio = 0.5*(float(use.gpu+float(use.memory)))
+ return ratio
+
+ deviceCount = pynvml.nvmlDeviceGetCount()
+ available = []
+ for i in range(deviceCount):
+ if getFreeRatio(i)<70:
+ available.append(i)
+ gpus = ''
+ for g in available:
+ gpus = gpus+str(g)+','
+ gpus = gpus[:-1]
+ return gpus
+
+def setgpu(gpuinput):
+ freeids = getFreeId()
+ if gpuinput=='all':
+ gpus = freeids
+ else:
+ gpus = gpuinput
+ if any([g not in freeids for g in gpus.split(',')]):
+ raise ValueError('gpu'+g+'is being used')
+ print('using gpu '+gpus)
+ os.environ['CUDA_VISIBLE_DEVICES']=gpus
+ return len(gpus.split(','))
+
+class Logger(object):
+ def __init__(self,logfile):
+ self.terminal = sys.stdout
+ self.log = open(logfile, "a")
+
+ def write(self, message):
+ self.terminal.write(message)
+ self.log.write(message)
+
+ def flush(self):
+ #this flush method is needed for python 3 compatibility.
+ #this handles the flush command by doing nothing.
+ #you might want to specify some extra behavior here.
+ pass
+
+
+def split4(data, max_stride, margin):
+ splits = []
+ data = torch.Tensor.numpy(data)
+ _,c, z, h, w = data.shape
+
+ w_width = np.ceil(float(w / 2 + margin)/max_stride).astype('int')*max_stride
+ h_width = np.ceil(float(h / 2 + margin)/max_stride).astype('int')*max_stride
+ pad = int(np.ceil(float(z)/max_stride)*max_stride)-z
+ leftpad = pad/2
+ pad = [[0,0],[0,0],[leftpad,pad-leftpad],[0,0],[0,0]]
+ data = np.pad(data,pad,'constant',constant_values=-1)
+ data = torch.from_numpy(data)
+ splits.append(data[:, :, :, :h_width, :w_width])
+ splits.append(data[:, :, :, :h_width, -w_width:])
+ splits.append(data[:, :, :, -h_width:, :w_width])
+ splits.append(data[:, :, :, -h_width:, -w_width:])
+
+ return torch.cat(splits, 0)
+
+def combine4(output, h, w):
+ splits = []
+ for i in range(len(output)):
+ splits.append(output[i])
+
+ output = np.zeros((
+ splits[0].shape[0],
+ h,
+ w,
+ splits[0].shape[3],
+ splits[0].shape[4]), np.float32)
+
+ h0 = output.shape[1] / 2
+ h1 = output.shape[1] - h0
+ w0 = output.shape[2] / 2
+ w1 = output.shape[2] - w0
+
+ splits[0] = splits[0][:, :h0, :w0, :, :]
+ output[:, :h0, :w0, :, :] = splits[0]
+
+ splits[1] = splits[1][:, :h0, -w1:, :, :]
+ output[:, :h0, -w1:, :, :] = splits[1]
+
+ splits[2] = splits[2][:, -h1:, :w0, :, :]
+ output[:, -h1:, :w0, :, :] = splits[2]
+
+ splits[3] = splits[3][:, -h1:, -w1:, :, :]
+ output[:, -h1:, -w1:, :, :] = splits[3]
+
+ return output
+
+def split8(data, max_stride, margin):
+ splits = []
+ if isinstance(data, np.ndarray):
+ c, z, h, w = data.shape
+ else:
+ _,c, z, h, w = data.size()
+
+ z_width = np.ceil(float(z / 2 + margin)/max_stride).astype('int')*max_stride
+ w_width = np.ceil(float(w / 2 + margin)/max_stride).astype('int')*max_stride
+ h_width = np.ceil(float(h / 2 + margin)/max_stride).astype('int')*max_stride
+ for zz in [[0,z_width],[-z_width,None]]:
+ for hh in [[0,h_width],[-h_width,None]]:
+ for ww in [[0,w_width],[-w_width,None]]:
+ if isinstance(data, np.ndarray):
+ splits.append(data[np.newaxis, :, zz[0]:zz[1], hh[0]:hh[1], ww[0]:ww[1]])
+ else:
+ splits.append(data[:, :, zz[0]:zz[1], hh[0]:hh[1], ww[0]:ww[1]])
+
+
+ if isinstance(data, np.ndarray):
+ return np.concatenate(splits, 0)
+ else:
+ return torch.cat(splits, 0)
+
+
+
+def combine8(output, z, h, w):
+ splits = []
+ for i in range(len(output)):
+ splits.append(output[i])
+
+ output = np.zeros((
+ z,
+ h,
+ w,
+ splits[0].shape[3],
+ splits[0].shape[4]), np.float32)
+
+
+ z_width = z / 2
+ h_width = h / 2
+ w_width = w / 2
+ i = 0
+ for zz in [[0,z_width],[z_width-z,None]]:
+ for hh in [[0,h_width],[h_width-h,None]]:
+ for ww in [[0,w_width],[w_width-w,None]]:
+ output[zz[0]:zz[1], hh[0]:hh[1], ww[0]:ww[1], :, :] = splits[i][zz[0]:zz[1], hh[0]:hh[1], ww[0]:ww[1], :, :]
+ i = i+1
+
+ return output
+
+
+def split16(data, max_stride, margin):
+ splits = []
+ _,c, z, h, w = data.size()
+
+ z_width = np.ceil(float(z / 4 + margin)/max_stride).astype('int')*max_stride
+ z_pos = [z*3/8-z_width/2,
+ z*5/8-z_width/2]
+ h_width = np.ceil(float(h / 2 + margin)/max_stride).astype('int')*max_stride
+ w_width = np.ceil(float(w / 2 + margin)/max_stride).astype('int')*max_stride
+ for zz in [[0,z_width],[z_pos[0],z_pos[0]+z_width],[z_pos[1],z_pos[1]+z_width],[-z_width,None]]:
+ for hh in [[0,h_width],[-h_width,None]]:
+ for ww in [[0,w_width],[-w_width,None]]:
+ splits.append(data[:, :, zz[0]:zz[1], hh[0]:hh[1], ww[0]:ww[1]])
+
+ return torch.cat(splits, 0)
+
+def combine16(output, z, h, w):
+ splits = []
+ for i in range(len(output)):
+ splits.append(output[i])
+
+ output = np.zeros((
+ z,
+ h,
+ w,
+ splits[0].shape[3],
+ splits[0].shape[4]), np.float32)
+
+
+ z_width = z / 4
+ h_width = h / 2
+ w_width = w / 2
+ splitzstart = splits[0].shape[0]/2-z_width/2
+ z_pos = [z*3/8-z_width/2,
+ z*5/8-z_width/2]
+ i = 0
+ for zz,zz2 in zip([[0,z_width],[z_width,z_width*2],[z_width*2,z_width*3],[z_width*3-z,None]],
+ [[0,z_width],[splitzstart,z_width+splitzstart],[splitzstart,z_width+splitzstart],[z_width*3-z,None]]):
+ for hh in [[0,h_width],[h_width-h,None]]:
+ for ww in [[0,w_width],[w_width-w,None]]:
+ output[zz[0]:zz[1], hh[0]:hh[1], ww[0]:ww[1], :, :] = splits[i][zz2[0]:zz2[1], hh[0]:hh[1], ww[0]:ww[1], :, :]
+ i = i+1
+
+ return output
+
+def split32(data, max_stride, margin):
+ splits = []
+ _,c, z, h, w = data.size()
+
+ z_width = np.ceil(float(z / 2 + margin)/max_stride).astype('int')*max_stride
+ w_width = np.ceil(float(w / 4 + margin)/max_stride).astype('int')*max_stride
+ h_width = np.ceil(float(h / 4 + margin)/max_stride).astype('int')*max_stride
+
+ w_pos = [w*3/8-w_width/2,
+ w*5/8-w_width/2]
+ h_pos = [h*3/8-h_width/2,
+ h*5/8-h_width/2]
+
+ for zz in [[0,z_width],[-z_width,None]]:
+ for hh in [[0,h_width],[h_pos[0],h_pos[0]+h_width],[h_pos[1],h_pos[1]+h_width],[-h_width,None]]:
+ for ww in [[0,w_width],[w_pos[0],w_pos[0]+w_width],[w_pos[1],w_pos[1]+w_width],[-w_width,None]]:
+ splits.append(data[:, :, zz[0]:zz[1], hh[0]:hh[1], ww[0]:ww[1]])
+
+ return torch.cat(splits, 0)
+
+def combine32(splits, z, h, w):
+
+ output = np.zeros((
+ z,
+ h,
+ w,
+ splits[0].shape[3],
+ splits[0].shape[4]), np.float32)
+
+
+ z_width = int(np.ceil(float(z) / 2))
+ h_width = int(np.ceil(float(h) / 4))
+ w_width = int(np.ceil(float(w) / 4))
+ splithstart = splits[0].shape[1]/2-h_width/2
+ splitwstart = splits[0].shape[2]/2-w_width/2
+
+ i = 0
+ for zz in [[0,z_width],[z_width-z,None]]:
+
+ for hh,hh2 in zip([[0,h_width],[h_width,h_width*2],[h_width*2,h_width*3],[h_width*3-h,None]],
+ [[0,h_width],[splithstart,h_width+splithstart],[splithstart,h_width+splithstart],[h_width*3-h,None]]):
+
+ for ww,ww2 in zip([[0,w_width],[w_width,w_width*2],[w_width*2,w_width*3],[w_width*3-w,None]],
+ [[0,w_width],[splitwstart,w_width+splitwstart],[splitwstart,w_width+splitwstart],[w_width*3-w,None]]):
+
+ output[zz[0]:zz[1], hh[0]:hh[1], ww[0]:ww[1], :, :] = splits[i][zz[0]:zz[1], hh2[0]:hh2[1], ww2[0]:ww2[1], :, :]
+ i = i+1
+
+ return output
+
+
+
+def split64(data, max_stride, margin):
+ splits = []
+ _,c, z, h, w = data.size()
+
+ z_width = np.ceil(float(z / 4 + margin)/max_stride).astype('int')*max_stride
+ w_width = np.ceil(float(w / 4 + margin)/max_stride).astype('int')*max_stride
+ h_width = np.ceil(float(h / 4 + margin)/max_stride).astype('int')*max_stride
+
+ z_pos = [z*3/8-z_width/2,
+ z*5/8-z_width/2]
+ w_pos = [w*3/8-w_width/2,
+ w*5/8-w_width/2]
+ h_pos = [h*3/8-h_width/2,
+ h*5/8-h_width/2]
+
+ for zz in [[0,z_width],[z_pos[0],z_pos[0]+z_width],[z_pos[1],z_pos[1]+z_width],[-z_width,None]]:
+ for hh in [[0,h_width],[h_pos[0],h_pos[0]+h_width],[h_pos[1],h_pos[1]+h_width],[-h_width,None]]:
+ for ww in [[0,w_width],[w_pos[0],w_pos[0]+w_width],[w_pos[1],w_pos[1]+w_width],[-w_width,None]]:
+ splits.append(data[:, :, zz[0]:zz[1], hh[0]:hh[1], ww[0]:ww[1]])
+
+ return torch.cat(splits, 0)
+
+def combine64(output, z, h, w):
+ splits = []
+ for i in range(len(output)):
+ splits.append(output[i])
+
+ output = np.zeros((
+ z,
+ h,
+ w,
+ splits[0].shape[3],
+ splits[0].shape[4]), np.float32)
+
+
+ z_width = int(np.ceil(float(z) / 4))
+ h_width = int(np.ceil(float(h) / 4))
+ w_width = int(np.ceil(float(w) / 4))
+ splitzstart = splits[0].shape[0]/2-z_width/2
+ splithstart = splits[0].shape[1]/2-h_width/2
+ splitwstart = splits[0].shape[2]/2-w_width/2
+
+ i = 0
+ for zz,zz2 in zip([[0,z_width],[z_width,z_width*2],[z_width*2,z_width*3],[z_width*3-z,None]],
+ [[0,z_width],[splitzstart,z_width+splitzstart],[splitzstart,z_width+splitzstart],[z_width*3-z,None]]):
+
+ for hh,hh2 in zip([[0,h_width],[h_width,h_width*2],[h_width*2,h_width*3],[h_width*3-h,None]],
+ [[0,h_width],[splithstart,h_width+splithstart],[splithstart,h_width+splithstart],[h_width*3-h,None]]):
+
+ for ww,ww2 in zip([[0,w_width],[w_width,w_width*2],[w_width*2,w_width*3],[w_width*3-w,None]],
+ [[0,w_width],[splitwstart,w_width+splitwstart],[splitwstart,w_width+splitwstart],[w_width*3-w,None]]):
+
+ output[zz[0]:zz[1], hh[0]:hh[1], ww[0]:ww[1], :, :] = splits[i][zz2[0]:zz2[1], hh2[0]:hh2[1], ww2[0]:ww2[1], :, :]
+ i = i+1
+
+ return output
diff --git a/training/detector/valsplit.npy b/training/detector/valsplit.npy
new file mode 100644
index 0000000..a6aa141
Binary files /dev/null and b/training/detector/valsplit.npy differ
diff --git a/training/prepare.py b/training/prepare.py
new file mode 100644
index 0000000..5473dbe
--- /dev/null
+++ b/training/prepare.py
@@ -0,0 +1,373 @@
+import os
+import shutil
+import numpy as np
+from config_training import config
+
+
+from scipy.io import loadmat
+import numpy as np
+import h5py
+import pandas
+import scipy
+from scipy.ndimage.interpolation import zoom
+from skimage import measure
+import SimpleITK as sitk
+from scipy.ndimage.morphology import binary_dilation,generate_binary_structure
+from skimage.morphology import convex_hull_image
+import pandas
+from multiprocessing import Pool
+from functools import partial
+import sys
+sys.path.append('../preprocessing')
+from step1 import step1_python
+import warnings
+
+def resample(imgs, spacing, new_spacing,order=2):
+ if len(imgs.shape)==3:
+ new_shape = np.round(imgs.shape * spacing / new_spacing)
+ true_spacing = spacing * imgs.shape / new_shape
+ resize_factor = new_shape / imgs.shape
+ imgs = zoom(imgs, resize_factor, mode = 'nearest',order=order)
+ return imgs, true_spacing
+ elif len(imgs.shape)==4:
+ n = imgs.shape[-1]
+ newimg = []
+ for i in range(n):
+ slice = imgs[:,:,:,i]
+ newslice,true_spacing = resample(slice,spacing,new_spacing)
+ newimg.append(newslice)
+ newimg=np.transpose(np.array(newimg),[1,2,3,0])
+ return newimg,true_spacing
+ else:
+ raise ValueError('wrong shape')
+def worldToVoxelCoord(worldCoord, origin, spacing):
+
+ stretchedVoxelCoord = np.absolute(worldCoord - origin)
+ voxelCoord = stretchedVoxelCoord / spacing
+ return voxelCoord
+
+def load_itk_image(filename):
+ with open(filename) as f:
+ contents = f.readlines()
+ line = [k for k in contents if k.startswith('TransformMatrix')][0]
+ transformM = np.array(line.split(' = ')[1].split(' ')).astype('float')
+ transformM = np.round(transformM)
+ if np.any( transformM!=np.array([1,0,0, 0, 1, 0, 0, 0, 1])):
+ isflip = True
+ else:
+ isflip = False
+
+ itkimage = sitk.ReadImage(filename)
+ numpyImage = sitk.GetArrayFromImage(itkimage)
+
+ numpyOrigin = np.array(list(reversed(itkimage.GetOrigin())))
+ numpySpacing = np.array(list(reversed(itkimage.GetSpacing())))
+
+ return numpyImage, numpyOrigin, numpySpacing,isflip
+
+def process_mask(mask):
+ convex_mask = np.copy(mask)
+ for i_layer in range(convex_mask.shape[0]):
+ mask1 = np.ascontiguousarray(mask[i_layer])
+ if np.sum(mask1)>0:
+ mask2 = convex_hull_image(mask1)
+ if np.sum(mask2)>1.5*np.sum(mask1):
+ mask2 = mask1
+ else:
+ mask2 = mask1
+ convex_mask[i_layer] = mask2
+ struct = generate_binary_structure(3,1)
+ dilatedMask = binary_dilation(convex_mask,structure=struct,iterations=10)
+ return dilatedMask
+
+
+def lumTrans(img):
+ lungwin = np.array([-1200.,600.])
+ newimg = (img-lungwin[0])/(lungwin[1]-lungwin[0])
+ newimg[newimg<0]=0
+ newimg[newimg>1]=1
+ newimg = (newimg*255).astype('uint8')
+ return newimg
+
+
+def savenpy(id,annos,filelist,data_path,prep_folder):
+ resolution = np.array([1,1,1])
+ name = filelist[id]
+ label = annos[annos[:,0]==name]
+ label = label[:,[3,1,2,4]].astype('float')
+
+ im, m1, m2, spacing = step1_python(os.path.join(data_path,name))
+ Mask = m1+m2
+
+ newshape = np.round(np.array(Mask.shape)*spacing/resolution)
+ xx,yy,zz= np.where(Mask)
+ box = np.array([[np.min(xx),np.max(xx)],[np.min(yy),np.max(yy)],[np.min(zz),np.max(zz)]])
+ box = box*np.expand_dims(spacing,1)/np.expand_dims(resolution,1)
+ box = np.floor(box).astype('int')
+ margin = 5
+ extendbox = np.vstack([np.max([[0,0,0],box[:,0]-margin],0),np.min([newshape,box[:,1]+2*margin],axis=0).T]).T
+ extendbox = extendbox.astype('int')
+
+
+
+ convex_mask = m1
+ dm1 = process_mask(m1)
+ dm2 = process_mask(m2)
+ dilatedMask = dm1+dm2
+ Mask = m1+m2
+ extramask = dilatedMask - Mask
+ bone_thresh = 210
+ pad_value = 170
+ im[np.isnan(im)]=-2000
+ sliceim = lumTrans(im)
+ sliceim = sliceim*dilatedMask+pad_value*(1-dilatedMask).astype('uint8')
+ bones = sliceim*extramask>bone_thresh
+ sliceim[bones] = pad_value
+ sliceim1,_ = resample(sliceim,spacing,resolution,order=1)
+ sliceim2 = sliceim1[extendbox[0,0]:extendbox[0,1],
+ extendbox[1,0]:extendbox[1,1],
+ extendbox[2,0]:extendbox[2,1]]
+ sliceim = sliceim2[np.newaxis,...]
+ np.save(os.path.join(prep_folder,name+'_clean.npy'),sliceim)
+
+
+ if len(label)==0:
+ label2 = np.array([[0,0,0,0]])
+ elif len(label[0])==0:
+ label2 = np.array([[0,0,0,0]])
+ elif label[0][0]==0:
+ label2 = np.array([[0,0,0,0]])
+ else:
+ haslabel = 1
+ label2 = np.copy(label).T
+ label2[:3] = label2[:3][[0,2,1]]
+ label2[:3] = label2[:3]*np.expand_dims(spacing,1)/np.expand_dims(resolution,1)
+ label2[3] = label2[3]*spacing[1]/resolution[1]
+ label2[:3] = label2[:3]-np.expand_dims(extendbox[:,0],1)
+ label2 = label2[:4].T
+ np.save(os.path.join(prep_folder,name+'_label.npy'),label2)
+
+ print(name)
+
+def full_prep(step1=True,step2 = True):
+ warnings.filterwarnings("ignore")
+
+ #preprocess_result_path = './prep_result'
+ prep_folder = config['preprocess_result_path']
+ data_path = config['stage1_data_path']
+ finished_flag = '.flag_prepkaggle'
+
+ if not os.path.exists(finished_flag):
+ alllabelfiles = config['stage1_annos_path']
+ tmp = []
+ for f in alllabelfiles:
+ content = np.array(pandas.read_csv(f))
+ content = content[content[:,0]!=np.nan]
+ tmp.append(content[:,:5])
+ alllabel = np.concatenate(tmp,0)
+ filelist = os.listdir(config['stage1_data_path'])
+
+ if not os.path.exists(prep_folder):
+ os.mkdir(prep_folder)
+ #eng.addpath('preprocessing/',nargout=0)
+
+ print('starting preprocessing')
+ pool = Pool()
+ filelist = [f for f in os.listdir(data_path)]
+ partial_savenpy = partial(savenpy,annos= alllabel,filelist=filelist,data_path=data_path,prep_folder=prep_folder )
+
+ N = len(filelist)
+ #savenpy(1)
+ _=pool.map(partial_savenpy,range(N))
+ pool.close()
+ pool.join()
+ print('end preprocessing')
+ f= open(finished_flag,"w+")
+
+def savenpy_luna(id,annos,filelist,luna_segment,luna_data,savepath):
+ islabel = True
+ isClean = True
+ resolution = np.array([1,1,1])
+# resolution = np.array([2,2,2])
+ name = filelist[id]
+
+ Mask,origin,spacing,isflip = load_itk_image(os.path.join(luna_segment,name+'.mhd'))
+ if isflip:
+ Mask = Mask[:,::-1,::-1]
+ newshape = np.round(np.array(Mask.shape)*spacing/resolution).astype('int')
+ m1 = Mask==3
+ m2 = Mask==4
+ Mask = m1+m2
+
+ xx,yy,zz= np.where(Mask)
+ box = np.array([[np.min(xx),np.max(xx)],[np.min(yy),np.max(yy)],[np.min(zz),np.max(zz)]])
+ box = box*np.expand_dims(spacing,1)/np.expand_dims(resolution,1)
+ box = np.floor(box).astype('int')
+ margin = 5
+ extendbox = np.vstack([np.max([[0,0,0],box[:,0]-margin],0),np.min([newshape,box[:,1]+2*margin],axis=0).T]).T
+
+ this_annos = np.copy(annos[annos[:,0]==int(name)])
+
+ if isClean:
+ convex_mask = m1
+ dm1 = process_mask(m1)
+ dm2 = process_mask(m2)
+ dilatedMask = dm1+dm2
+ Mask = m1+m2
+ extramask = dilatedMask ^ Mask
+ bone_thresh = 210
+ pad_value = 170
+
+ sliceim,origin,spacing,isflip = load_itk_image(os.path.join(luna_data,name+'.mhd'))
+ sliceim = lumTrans(sliceim)
+ sliceim = sliceim*dilatedMask+pad_value*(1-dilatedMask).astype('uint8')
+ bones = (sliceim*extramask)>bone_thresh
+ sliceim[bones] = pad_value
+
+ sliceim1,_ = resample(sliceim,spacing,resolution,order=1)
+ sliceim2 = sliceim1[extendbox[0,0]:extendbox[0,1],
+ extendbox[1,0]:extendbox[1,1],
+ extendbox[2,0]:extendbox[2,1]]
+ sliceim = sliceim2[np.newaxis,...]
+ np.save(os.path.join(savepath,name+'_clean.npy'),sliceim)
+
+
+ if islabel:
+
+ this_annos = np.copy(annos[annos[:,0]==int(name)])
+ label = []
+ if len(this_annos)>0:
+
+ for c in this_annos:
+ pos = worldToVoxelCoord(c[1:4][::-1],origin=origin,spacing=spacing)
+ if isflip:
+ pos[1:] = Mask.shape[1:3]-pos[1:]
+ label.append(np.concatenate([pos,[c[4]/spacing[1]]]))
+
+ label = np.array(label)
+ if len(label)==0:
+ label2 = np.array([[0,0,0,0]])
+ else:
+ label2 = np.copy(label).T
+ label2[:3] = label2[:3]*np.expand_dims(spacing,1)/np.expand_dims(resolution,1)
+ label2[3] = label2[3]*spacing[1]/resolution[1]
+ label2[:3] = label2[:3]-np.expand_dims(extendbox[:,0],1)
+ label2 = label2[:4].T
+ np.save(os.path.join(savepath,name+'_label.npy'),label2)
+
+ print(name)
+
+def preprocess_luna():
+ luna_segment = config['luna_segment']
+ savepath = config['preprocess_result_path']
+ luna_data = config['luna_data']
+ luna_label = config['luna_label']
+ finished_flag = '.flag_preprocessluna'
+ print('starting preprocessing luna')
+ if not os.path.exists(finished_flag):
+ filelist = [f.split('.mhd')[0] for f in os.listdir(luna_data) if f.endswith('.mhd') ]
+ annos = np.array(pandas.read_csv(luna_label))
+
+ if not os.path.exists(savepath):
+ os.mkdir(savepath)
+
+
+ pool = Pool()
+ partial_savenpy_luna = partial(savenpy_luna,annos=annos,filelist=filelist,
+ luna_segment=luna_segment,luna_data=luna_data,savepath=savepath)
+
+ N = len(filelist)
+ #savenpy(1)
+ _=pool.map(partial_savenpy_luna,range(N))
+ pool.close()
+ pool.join()
+ print('end preprocessing luna')
+ f= open(finished_flag,"w+")
+
+def prepare_luna():
+ print('start changing luna name')
+ luna_raw = config['luna_raw']
+ luna_abbr = config['luna_abbr']
+ luna_data = config['luna_data']
+ luna_segment = config['luna_segment']
+ finished_flag = '.flag_prepareluna'
+
+ if not os.path.exists(finished_flag):
+
+ subsetdirs = [os.path.join(luna_raw,f) for f in os.listdir(luna_raw) if f.startswith('subset') and os.path.isdir(os.path.join(luna_raw,f))]
+ if not os.path.exists(luna_data):
+ os.mkdir(luna_data)
+
+# allnames = []
+# for d in subsetdirs:
+# files = os.listdir(d)
+# names = [f[:-4] for f in files if f.endswith('mhd')]
+# allnames = allnames + names
+# allnames = np.array(allnames)
+# allnames = np.sort(allnames)
+
+# ids = np.arange(len(allnames)).astype('str')
+# ids = np.array(['0'*(3-len(n))+n for n in ids])
+# pds = pandas.DataFrame(np.array([ids,allnames]).T)
+# namelist = list(allnames)
+
+ abbrevs = np.array(pandas.read_csv(config['luna_abbr'],header=None))
+ namelist = list(abbrevs[:,1])
+ ids = abbrevs[:,0]
+
+ for d in subsetdirs:
+ files = os.listdir(d)
+ files.sort()
+ for f in files:
+ name = f[:-4]
+ id = ids[namelist.index(name)]
+ shutil.move(os.path.join(d,f),os.path.join(luna_data,str(id)+f[-4:]))
+ print(os.path.join(luna_data,str(id)+f[-4:]))
+
+ files = [f for f in os.listdir(luna_data) if f.endswith('mhd')]
+ for file in files:
+ with open(os.path.join(luna_data,file),'r') as f:
+ content = f.readlines()
+ id = file.split('.mhd')[0]
+ filename = '0'*(3-len(str(id)))+str(id)
+ content[-1]='ElementDataFile = '+filename+'.raw\n'
+ print(content[-1])
+ with open(os.path.join(luna_data,file),'w') as f:
+ f.writelines(content)
+
+
+ seglist = os.listdir(luna_segment)
+ for f in seglist:
+ if f.endswith('.mhd'):
+
+ name = f[:-4]
+ lastfix = f[-4:]
+ else:
+ name = f[:-5]
+ lastfix = f[-5:]
+ if name in namelist:
+ id = ids[namelist.index(name)]
+ filename = '0'*(3-len(str(id)))+str(id)
+
+ shutil.move(os.path.join(luna_segment,f),os.path.join(luna_segment,filename+lastfix))
+ print(os.path.join(luna_segment,filename+lastfix))
+
+
+ files = [f for f in os.listdir(luna_segment) if f.endswith('mhd')]
+ for file in files:
+ with open(os.path.join(luna_segment,file),'r') as f:
+ content = f.readlines()
+ id = file.split('.mhd')[0]
+ filename = '0'*(3-len(str(id)))+str(id)
+ content[-1]='ElementDataFile = '+filename+'.zraw\n'
+ print(content[-1])
+ with open(os.path.join(luna_segment,file),'w') as f:
+ f.writelines(content)
+ print('end changing luna name')
+ f= open(finished_flag,"w+")
+
+if __name__=='__main__':
+ full_prep(step1=True,step2=True)
+ prepare_luna()
+ preprocess_luna()
+
diff --git a/training/run_training.sh b/training/run_training.sh
new file mode 100644
index 0000000..6ec7ce5
--- /dev/null
+++ b/training/run_training.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+set -e
+
+python prepare.py
+cd detector
+eps=100
+CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7,8 python main.py --model res18 -b 32 --epochs $eps --save-dir res18
+CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7,8 python main.py --model res18 -b 32 --resume results/res18/$eps.ckpt --test 1
+cp results/res18/$eps.ckpt ../../model/detector.ckpt
+
+
+cd ../classifier
+python adapt_ckpt.py --model1 net_detector_3 --model2 net_classifier_3 --resume ../detector/results/res18/$eps.ckpt
+CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7,8 python main.py --model1 net_detector_3 --model2 net_classifier_3 -b 32 -b2 12 --save-dir net3 --resume ./results/start.ckpt --start-epoch 30 --epochs 130
+CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7,8 python main.py --model1 net_detector_3 --model2 net_classifier_4 -b 32 -b2 12 --save-dir net4 --resume ./results/net3/130.ckpt --freeze_batchnorm 1 --start-epoch 121
+cp results/net4/160.ckpt ../../model/classifier.ckpt
diff --git a/utils.py b/utils.py
new file mode 100644
index 0000000..8743c82
--- /dev/null
+++ b/utils.py
@@ -0,0 +1,308 @@
+import sys
+import os
+import numpy as np
+import torch
+def getFreeId():
+ import pynvml
+
+ pynvml.nvmlInit()
+ def getFreeRatio(id):
+ handle = pynvml.nvmlDeviceGetHandleByIndex(id)
+ use = pynvml.nvmlDeviceGetUtilizationRates(handle)
+ ratio = 0.5*(float(use.gpu+float(use.memory)))
+ return ratio
+
+ deviceCount = pynvml.nvmlDeviceGetCount()
+ available = []
+ for i in range(deviceCount):
+ if getFreeRatio(i)<70:
+ available.append(i)
+ gpus = ''
+ for g in available:
+ gpus = gpus+str(g)+','
+ gpus = gpus[:-1]
+ return gpus
+
+def setgpu(gpuinput):
+ freeids = getFreeId()
+ if gpuinput=='all':
+ gpus = freeids
+ else:
+ gpus = gpuinput
+ if any([g not in freeids for g in gpus.split(',')]):
+ raise ValueError('gpu'+g+'is being used')
+ print('using gpu '+gpus)
+ os.environ['CUDA_VISIBLE_DEVICES']=gpus
+ return len(gpus.split(','))
+
+class Logger(object):
+ def __init__(self,logfile):
+ self.terminal = sys.stdout
+ self.log = open(logfile, "a")
+
+ def write(self, message):
+ self.terminal.write(message)
+ self.log.write(message)
+
+ def flush(self):
+ #this flush method is needed for python 3 compatibility.
+ #this handles the flush command by doing nothing.
+ #you might want to specify some extra behavior here.
+ pass
+
+
+def split4(data, max_stride, margin):
+ splits = []
+ data = torch.Tensor.numpy(data)
+ _,c, z, h, w = data.shape
+
+ w_width = np.ceil(float(w / 2 + margin)/max_stride).astype('int')*max_stride
+ h_width = np.ceil(float(h / 2 + margin)/max_stride).astype('int')*max_stride
+ pad = int(np.ceil(float(z)/max_stride)*max_stride)-z
+ leftpad = pad/2
+ pad = [[0,0],[0,0],[leftpad,pad-leftpad],[0,0],[0,0]]
+ data = np.pad(data,pad,'constant',constant_values=-1)
+ data = torch.from_numpy(data)
+ splits.append(data[:, :, :, :h_width, :w_width])
+ splits.append(data[:, :, :, :h_width, -w_width:])
+ splits.append(data[:, :, :, -h_width:, :w_width])
+ splits.append(data[:, :, :, -h_width:, -w_width:])
+
+ return torch.cat(splits, 0)
+
+def combine4(output, h, w):
+ splits = []
+ for i in range(len(output)):
+ splits.append(output[i])
+
+ output = np.zeros((
+ splits[0].shape[0],
+ h,
+ w,
+ splits[0].shape[3],
+ splits[0].shape[4]), np.float32)
+
+ h0 = output.shape[1] / 2
+ h1 = output.shape[1] - h0
+ w0 = output.shape[2] / 2
+ w1 = output.shape[2] - w0
+
+ splits[0] = splits[0][:, :h0, :w0, :, :]
+ output[:, :h0, :w0, :, :] = splits[0]
+
+ splits[1] = splits[1][:, :h0, -w1:, :, :]
+ output[:, :h0, -w1:, :, :] = splits[1]
+
+ splits[2] = splits[2][:, -h1:, :w0, :, :]
+ output[:, -h1:, :w0, :, :] = splits[2]
+
+ splits[3] = splits[3][:, -h1:, -w1:, :, :]
+ output[:, -h1:, -w1:, :, :] = splits[3]
+
+ return output
+
+def split8(data, max_stride, margin):
+ splits = []
+ if isinstance(data, np.ndarray):
+ c, z, h, w = data.shape
+ else:
+ _,c, z, h, w = data.size()
+
+ z_width = np.ceil(float(z / 2 + margin)/max_stride).astype('int')*max_stride
+ w_width = np.ceil(float(w / 2 + margin)/max_stride).astype('int')*max_stride
+ h_width = np.ceil(float(h / 2 + margin)/max_stride).astype('int')*max_stride
+ for zz in [[0,z_width],[-z_width,None]]:
+ for hh in [[0,h_width],[-h_width,None]]:
+ for ww in [[0,w_width],[-w_width,None]]:
+ if isinstance(data, np.ndarray):
+ splits.append(data[np.newaxis, :, zz[0]:zz[1], hh[0]:hh[1], ww[0]:ww[1]])
+ else:
+ splits.append(data[:, :, zz[0]:zz[1], hh[0]:hh[1], ww[0]:ww[1]])
+
+
+ if isinstance(data, np.ndarray):
+ return np.concatenate(splits, 0)
+ else:
+ return torch.cat(splits, 0)
+
+
+
+def combine8(output, z, h, w):
+ splits = []
+ for i in range(len(output)):
+ splits.append(output[i])
+
+ output = np.zeros((
+ z,
+ h,
+ w,
+ splits[0].shape[3],
+ splits[0].shape[4]), np.float32)
+
+
+ z_width = z / 2
+ h_width = h / 2
+ w_width = w / 2
+ i = 0
+ for zz in [[0,z_width],[z_width-z,None]]:
+ for hh in [[0,h_width],[h_width-h,None]]:
+ for ww in [[0,w_width],[w_width-w,None]]:
+ output[zz[0]:zz[1], hh[0]:hh[1], ww[0]:ww[1], :, :] = splits[i][zz[0]:zz[1], hh[0]:hh[1], ww[0]:ww[1], :, :]
+ i = i+1
+
+ return output
+
+
+def split16(data, max_stride, margin):
+ splits = []
+ _,c, z, h, w = data.size()
+
+ z_width = np.ceil(float(z / 4 + margin)/max_stride).astype('int')*max_stride
+ z_pos = [z*3/8-z_width/2,
+ z*5/8-z_width/2]
+ h_width = np.ceil(float(h / 2 + margin)/max_stride).astype('int')*max_stride
+ w_width = np.ceil(float(w / 2 + margin)/max_stride).astype('int')*max_stride
+ for zz in [[0,z_width],[z_pos[0],z_pos[0]+z_width],[z_pos[1],z_pos[1]+z_width],[-z_width,None]]:
+ for hh in [[0,h_width],[-h_width,None]]:
+ for ww in [[0,w_width],[-w_width,None]]:
+ splits.append(data[:, :, zz[0]:zz[1], hh[0]:hh[1], ww[0]:ww[1]])
+
+ return torch.cat(splits, 0)
+
+def combine16(output, z, h, w):
+ splits = []
+ for i in range(len(output)):
+ splits.append(output[i])
+
+ output = np.zeros((
+ z,
+ h,
+ w,
+ splits[0].shape[3],
+ splits[0].shape[4]), np.float32)
+
+
+ z_width = z / 4
+ h_width = h / 2
+ w_width = w / 2
+ splitzstart = splits[0].shape[0]/2-z_width/2
+ z_pos = [z*3/8-z_width/2,
+ z*5/8-z_width/2]
+ i = 0
+ for zz,zz2 in zip([[0,z_width],[z_width,z_width*2],[z_width*2,z_width*3],[z_width*3-z,None]],
+ [[0,z_width],[splitzstart,z_width+splitzstart],[splitzstart,z_width+splitzstart],[z_width*3-z,None]]):
+ for hh in [[0,h_width],[h_width-h,None]]:
+ for ww in [[0,w_width],[w_width-w,None]]:
+ output[zz[0]:zz[1], hh[0]:hh[1], ww[0]:ww[1], :, :] = splits[i][zz2[0]:zz2[1], hh[0]:hh[1], ww[0]:ww[1], :, :]
+ i = i+1
+
+ return output
+
+def split32(data, max_stride, margin):
+ splits = []
+ _,c, z, h, w = data.size()
+
+ z_width = np.ceil(float(z / 2 + margin)/max_stride).astype('int')*max_stride
+ w_width = np.ceil(float(w / 4 + margin)/max_stride).astype('int')*max_stride
+ h_width = np.ceil(float(h / 4 + margin)/max_stride).astype('int')*max_stride
+
+ w_pos = [w*3/8-w_width/2,
+ w*5/8-w_width/2]
+ h_pos = [h*3/8-h_width/2,
+ h*5/8-h_width/2]
+
+ for zz in [[0,z_width],[-z_width,None]]:
+ for hh in [[0,h_width],[h_pos[0],h_pos[0]+h_width],[h_pos[1],h_pos[1]+h_width],[-h_width,None]]:
+ for ww in [[0,w_width],[w_pos[0],w_pos[0]+w_width],[w_pos[1],w_pos[1]+w_width],[-w_width,None]]:
+ splits.append(data[:, :, zz[0]:zz[1], hh[0]:hh[1], ww[0]:ww[1]])
+
+ return torch.cat(splits, 0)
+
+def combine32(splits, z, h, w):
+
+ output = np.zeros((
+ z,
+ h,
+ w,
+ splits[0].shape[3],
+ splits[0].shape[4]), np.float32)
+
+
+ z_width = int(np.ceil(float(z) / 2))
+ h_width = int(np.ceil(float(h) / 4))
+ w_width = int(np.ceil(float(w) / 4))
+ splithstart = splits[0].shape[1]/2-h_width/2
+ splitwstart = splits[0].shape[2]/2-w_width/2
+
+ i = 0
+ for zz in [[0,z_width],[z_width-z,None]]:
+
+ for hh,hh2 in zip([[0,h_width],[h_width,h_width*2],[h_width*2,h_width*3],[h_width*3-h,None]],
+ [[0,h_width],[splithstart,h_width+splithstart],[splithstart,h_width+splithstart],[h_width*3-h,None]]):
+
+ for ww,ww2 in zip([[0,w_width],[w_width,w_width*2],[w_width*2,w_width*3],[w_width*3-w,None]],
+ [[0,w_width],[splitwstart,w_width+splitwstart],[splitwstart,w_width+splitwstart],[w_width*3-w,None]]):
+
+ output[zz[0]:zz[1], hh[0]:hh[1], ww[0]:ww[1], :, :] = splits[i][zz[0]:zz[1], hh2[0]:hh2[1], ww2[0]:ww2[1], :, :]
+ i = i+1
+
+ return output
+
+
+
+def split64(data, max_stride, margin):
+ splits = []
+ _,c, z, h, w = data.size()
+
+ z_width = np.ceil(float(z / 4 + margin)/max_stride).astype('int')*max_stride
+ w_width = np.ceil(float(w / 4 + margin)/max_stride).astype('int')*max_stride
+ h_width = np.ceil(float(h / 4 + margin)/max_stride).astype('int')*max_stride
+
+ z_pos = [z*3/8-z_width/2,
+ z*5/8-z_width/2]
+ w_pos = [w*3/8-w_width/2,
+ w*5/8-w_width/2]
+ h_pos = [h*3/8-h_width/2,
+ h*5/8-h_width/2]
+
+ for zz in [[0,z_width],[z_pos[0],z_pos[0]+z_width],[z_pos[1],z_pos[1]+z_width],[-z_width,None]]:
+ for hh in [[0,h_width],[h_pos[0],h_pos[0]+h_width],[h_pos[1],h_pos[1]+h_width],[-h_width,None]]:
+ for ww in [[0,w_width],[w_pos[0],w_pos[0]+w_width],[w_pos[1],w_pos[1]+w_width],[-w_width,None]]:
+ splits.append(data[:, :, zz[0]:zz[1], hh[0]:hh[1], ww[0]:ww[1]])
+
+ return torch.cat(splits, 0)
+
+def combine64(output, z, h, w):
+ splits = []
+ for i in range(len(output)):
+ splits.append(output[i])
+
+ output = np.zeros((
+ z,
+ h,
+ w,
+ splits[0].shape[3],
+ splits[0].shape[4]), np.float32)
+
+
+ z_width = int(np.ceil(float(z) / 4))
+ h_width = int(np.ceil(float(h) / 4))
+ w_width = int(np.ceil(float(w) / 4))
+ splitzstart = splits[0].shape[0]/2-z_width/2
+ splithstart = splits[0].shape[1]/2-h_width/2
+ splitwstart = splits[0].shape[2]/2-w_width/2
+
+ i = 0
+ for zz,zz2 in zip([[0,z_width],[z_width,z_width*2],[z_width*2,z_width*3],[z_width*3-z,None]],
+ [[0,z_width],[splitzstart,z_width+splitzstart],[splitzstart,z_width+splitzstart],[z_width*3-z,None]]):
+
+ for hh,hh2 in zip([[0,h_width],[h_width,h_width*2],[h_width*2,h_width*3],[h_width*3-h,None]],
+ [[0,h_width],[splithstart,h_width+splithstart],[splithstart,h_width+splithstart],[h_width*3-h,None]]):
+
+ for ww,ww2 in zip([[0,w_width],[w_width,w_width*2],[w_width*2,w_width*3],[w_width*3-w,None]],
+ [[0,w_width],[splitwstart,w_width+splitwstart],[splitwstart,w_width+splitwstart],[w_width*3-w,None]]):
+
+ output[zz[0]:zz[1], hh[0]:hh[1], ww[0]:ww[1], :, :] = splits[i][zz2[0]:zz2[1], hh2[0]:hh2[1], ww2[0]:ww2[1], :, :]
+ i = i+1
+
+ return output