|
| 1 | +import os |
| 2 | +import sys |
| 3 | +import numpy as np |
| 4 | +import random |
| 5 | +import time |
| 6 | + |
| 7 | +import matplotlib.pyplot as plt |
| 8 | +import torch |
| 9 | +import torch.nn as nn |
| 10 | +import torch.nn.functional as F |
| 11 | + |
| 12 | + |
| 13 | +def translate_jets( batch, width=1.0 ): |
| 14 | + ''' |
| 15 | + Input: batch of jets, shape (batchsize, 3, n_constit) |
| 16 | + dim 1 ordering: (pT, eta, phi) |
| 17 | + Output: batch of eta-phi translated jets, same shape as input |
| 18 | + ''' |
| 19 | + mask = (batch[:,0] > 0) # 1 for constituents with non-zero pT, 0 otherwise |
| 20 | + ptp_eta = np.ptp(batch[:,1,:], axis=-1, keepdims=True) # ptp = 'peak to peak' = max - min |
| 21 | + ptp_phi = np.ptp(batch[:,2,:], axis=-1, keepdims=True) # ptp = 'peak to peak' = max - min |
| 22 | + low_eta = -width*ptp_eta |
| 23 | + high_eta = +width*ptp_eta |
| 24 | + low_phi = np.maximum(-width*ptp_phi, -np.pi-np.amin(batch[:,2,:], axis=1).reshape(ptp_phi.shape)) |
| 25 | + high_phi = np.minimum(+width*ptp_phi, +np.pi-np.amax(batch[:,2,:], axis=1).reshape(ptp_phi.shape)) |
| 26 | + shift_eta = mask*np.random.uniform(low=low_eta, high=high_eta, size=(batch.shape[0], 1)) |
| 27 | + shift_phi = mask*np.random.uniform(low=low_phi, high=high_phi, size=(batch.shape[0], 1)) |
| 28 | + shift = np.stack([np.zeros((batch.shape[0], batch.shape[2])), shift_eta, shift_phi], 1) |
| 29 | + shifted_batch = batch+shift |
| 30 | + return shifted_batch |
| 31 | + |
| 32 | + |
| 33 | +def rotate_jets( batch ): |
| 34 | + ''' |
| 35 | + Input: batch of jets, shape (batchsize, 3, n_constit) |
| 36 | + dim 1 ordering: (pT, eta, phi) |
| 37 | + Output: batch of jets rotated independently in eta-phi, same shape as input |
| 38 | + ''' |
| 39 | + rot_angle = np.random.rand(batch.shape[0])*2*np.pi |
| 40 | + c = np.cos(rot_angle) |
| 41 | + s = np.sin(rot_angle) |
| 42 | + o = np.ones_like(rot_angle) |
| 43 | + z = np.zeros_like(rot_angle) |
| 44 | + rot_matrix = np.array([[o, z, z], [z, c, -s], [z, s, c]]) # (3, 3, batchsize) |
| 45 | + return np.einsum('ijk,lji->ilk', batch, rot_matrix) |
| 46 | + |
| 47 | +def normalise_pts( batch ): |
| 48 | + ''' |
| 49 | + Input: batch of jets, shape (batchsize, 3, n_constit) |
| 50 | + dim 1 ordering: (pT, eta, phi) |
| 51 | + Output: batch of pT-normalised jets, pT in each jet sums to 1, same shape as input |
| 52 | + ''' |
| 53 | + batch_norm = batch.copy() |
| 54 | + batch_norm[:,0,:] = np.nan_to_num(batch_norm[:,0,:]/np.sum(batch_norm[:,0,:], axis=1)[:, np.newaxis], posinf = 0.0, neginf = 0.0 ) |
| 55 | + return batch_norm |
| 56 | + |
| 57 | +def rescale_pts( batch ): |
| 58 | + ''' |
| 59 | + Input: batch of jets, shape (batchsize, 3, n_constit) |
| 60 | + dim 1 ordering: (pT, eta, phi) |
| 61 | + Output: batch of pT-rescaled jets, each constituent pT is rescaled by 600, same shape as input |
| 62 | + ''' |
| 63 | + batch_rscl = batch.copy() |
| 64 | + batch_rscl[:,0,:] = np.nan_to_num(batch_rscl[:,0,:]/600, posinf = 0.0, neginf = 0.0 ) |
| 65 | + return batch_rscl |
| 66 | + |
| 67 | +def crop_jets( batch, nc ): |
| 68 | + ''' |
| 69 | + Input: batch of jets, shape (batchsize, 3, n_constit) |
| 70 | + dim 1 ordering: (pT, eta, phi) |
| 71 | + Output: batch of cropped jets, each jet is cropped to nc constituents, shape (batchsize, 3, nc) |
| 72 | + ''' |
| 73 | + batch_crop = batch.copy() |
| 74 | + return batch_crop[:,:,0:nc] |
| 75 | + |
| 76 | +def distort_jets( batch, strength=0.1, pT_clip_min=0.1 ): |
| 77 | + ''' |
| 78 | + Input: batch of jets, shape (batchsize, 3, n_constit) |
| 79 | + dim 1 ordering: (pT, eta, phi) |
| 80 | + Output: batch of jets with each constituents position shifted independently, shifts drawn from normal with mean 0, std strength/pT, same shape as input |
| 81 | + ''' |
| 82 | + pT = batch[:,0] # (batchsize, n_constit) |
| 83 | + shift_eta = np.nan_to_num( strength * np.random.randn(batch.shape[0], batch.shape[2]) / pT.clip(min=pT_clip_min), posinf = 0.0, neginf = 0.0 )# * mask |
| 84 | + shift_phi = np.nan_to_num( strength * np.random.randn(batch.shape[0], batch.shape[2]) / pT.clip(min=pT_clip_min), posinf = 0.0, neginf = 0.0 )# * mask |
| 85 | + shift = np.stack( [ np.zeros( (batch.shape[0], batch.shape[2]) ), shift_eta, shift_phi ], 1) |
| 86 | + return batch + shift |
| 87 | + |
| 88 | +def collinear_fill_jets( batch ): |
| 89 | + ''' |
| 90 | + Input: batch of jets, shape (batchsize, 3, n_constit) |
| 91 | + dim 1 ordering: (pT, eta, phi) |
| 92 | + Output: batch of jets with collinear splittings, the function attempts to fill as many of the zero-padded args.nconstit |
| 93 | + entries with collinear splittings of the constituents by splitting each constituent at most once, same shape as input |
| 94 | + ''' |
| 95 | + batchb = batch.copy() |
| 96 | + nc = batch.shape[2] |
| 97 | + nzs = np.array( [ np.where( batch[:,0,:][i]>0.0)[0].shape[0] for i in range(len(batch)) ] ) |
| 98 | + for k in range(len(batch)): |
| 99 | + nzs1 = np.max( [ nzs[k], int(nc/2) ] ) |
| 100 | + zs1 = int(nc-nzs1) |
| 101 | + els = np.random.choice( np.linspace(0,nzs1-1,nzs1), size=zs1, replace=False ) |
| 102 | + rs = np.random.uniform( size=zs1 ) |
| 103 | + for j in range(zs1): |
| 104 | + batchb[k,0,int(els[j])] = rs[j]*batch[k,0,int(els[j])] |
| 105 | + batchb[k,0,int(nzs[k]+j)] = (1-rs[j])*batch[k,0,int(els[j])] |
| 106 | + batchb[k,1,int(nzs[k]+j)] = batch[k,1,int(els[j])] |
| 107 | + batchb[k,2,int(nzs[k]+j)] = batch[k,2,int(els[j])] |
| 108 | + return batchb |
0 commit comments