**Introduction to Medical Imaging: Handling Dicom Files**

O Dicom é um formato de arquivo utilizado para armazenar exames médicos, como radiografias, tomografias, ressonâncias magnéticas, entre outros. Ele armazena vários metadados sobre o exame, como dados do paciente, a máquina usada para o exame, como a imagem é armazenada, informações espaciais e assim por diante. Cada exame tem propriedades diferentes, por isso é importante saber com qual tipo de exame você estará lidando em um projeto.

Aqui, mostraremos algumas dicas e truques básicos e essenciais ao manusear um arquivo dicom.

```python
!pip install -q condacolab
import condacolab
condacolab.install_miniconda()
!conda install -c conda-forge gdcm
!pip install pydicom==2.0.0

from google.colab import drive
drive.mount('/content/drive')
```

    ⏬ Downloading https://repo.anaconda.com/miniconda/Miniconda3-py37_4.9.2-Linux-x86_64.sh...
    📦 Installing...
    📌 Adjusting configuration...
    🩹 Patching environment...
    ⏲ Done in 0:00:21
    🔁 Restarting kernel...
    Collecting package metadata (current_repodata.json): - \ | / - \ | / - \ | / - \ | / - \ | / - \ | / - \ | / - \ | / - \ | / - \ | / - \ | / - \ | / - \ | / - \ | / - \ | / - \ | / - \ | / - \ | / - \ | / - \ | / - \ | / - \ | / - \ | / - done
    Solving environment: | / - \ | / - \ | / - \ | / - \ | / - \ | / - \ done

    ==> WARNING: A newer version of conda exists. <==
      current version: 4.9.2
      latest version: 4.11.0

    Please update conda by running

        $ conda update -n base -c defaults conda

    ## Package Plan ##

      environment location: /usr/local

      added / updated specs:
        - gdcm

    The following packages will be downloaded:

        package                    |            build
        ---------------------------|-----------------
        _libgcc_mutex-0.1          |      conda_forge           3 KB  conda-forge
        _openmp_mutex-4.5          |            1_gnu          22 KB  conda-forge
        ca-certificates-2021.10.8  |       ha878542_0         139 KB  conda-forge
        certifi-2021.10.8          |   py37h89c1867_1         145 KB  conda-forge
        conda-4.11.0               |   py37h89c1867_0        16.9 MB  conda-forge
        expat-2.4.4                |       h295c915_0         169 KB
        gdcm-2.8.9                 |   py37h500ead1_1         3.4 MB  conda-forge
        jpeg-9e                    |       h7f98852_0         269 KB  conda-forge
        json-c-0.13.1              |    hbfbb72e_1002          76 KB  conda-forge
        libgcc-ng-11.2.0           |      h1d223b6_13         906 KB  conda-forge
        libgomp-11.2.0             |      h1d223b6_13         428 KB  conda-forge
        libjpeg-turbo-2.1.1        |       h7f98852_0         981 KB  conda-forge
        libpng-1.6.37              |       h21135ba_2         306 KB  conda-forge
        libtiff-4.0.9              |    h648cc4a_1002         566 KB  conda-forge
        openjpeg-2.3.1             |       h58a6597_0         470 KB  conda-forge
        openssl-1.1.1l             |       h7f98852_0         2.1 MB  conda-forge
        python_abi-3.7             |          2_cp37m           4 KB  conda-forge
        ------------------------------------------------------------
                                               Total:        26.8 MB

    The following NEW packages will be INSTALLED:

      _openmp_mutex      conda-forge/linux-64::_openmp_mutex-4.5-1_gnu
      expat              pkgs/main/linux-64::expat-2.4.4-h295c915_0
      gdcm               conda-forge/linux-64::gdcm-2.8.9-py37h500ead1_1
      jpeg               conda-forge/linux-64::jpeg-9e-h7f98852_0
      json-c             conda-forge/linux-64::json-c-0.13.1-hbfbb72e_1002
      libgomp            conda-forge/linux-64::libgomp-11.2.0-h1d223b6_13
      libjpeg-turbo      conda-forge/linux-64::libjpeg-turbo-2.1.1-h7f98852_0
      libpng             conda-forge/linux-64::libpng-1.6.37-h21135ba_2
      libtiff            conda-forge/linux-64::libtiff-4.0.9-h648cc4a_1002
      openjpeg           conda-forge/linux-64::openjpeg-2.3.1-h58a6597_0
      python_abi         conda-forge/linux-64::python_abi-3.7-2_cp37m

    The following packages will be UPDATED:

      ca-certificates    pkgs/main::ca-certificates-2020.10.14~ --> conda-forge::ca-certificates-2021.10.8-ha878542_0
      certifi            pkgs/main/noarch::certifi-2020.6.20-p~ --> conda-forge/linux-64::certifi-2021.10.8-py37h89c1867_1
      conda               pkgs/main::conda-4.9.2-py37h06a4308_0 --> conda-forge::conda-4.11.0-py37h89c1867_0
      libgcc-ng           pkgs/main::libgcc-ng-9.1.0-hdf63c60_0 --> conda-forge::libgcc-ng-11.2.0-h1d223b6_13
      openssl              pkgs/main::openssl-1.1.1h-h7b6447c_0 --> conda-forge::openssl-1.1.1l-h7f98852_0

    The following packages will be SUPERSEDED by a higher-priority channel:

      _libgcc_mutex           pkgs/main::_libgcc_mutex-0.1-main --> conda-forge::_libgcc_mutex-0.1-conda_forge

    Downloading and Extracting Packages
    jpeg-9e              | 269 KB    | : 100% 1.0/1 [00:00<00:00,  8.02it/s]
    libgomp-11.2.0       | 428 KB    | : 100% 1.0/1 [00:00<00:00, 10.44it/s]
    libjpeg-turbo-2.1.1  | 981 KB    | : 100% 1.0/1 [00:00<00:00,  4.33it/s]
    expat-2.4.4          | 169 KB    | : 100% 1.0/1 [00:00<00:00,  9.84it/s]
    python_abi-3.7       | 4 KB      | : 100% 1.0/1 [00:00<00:00, 31.46it/s]
    _libgcc_mutex-0.1    | 3 KB      | : 100% 1.0/1 [00:00<00:00, 29.99it/s]
    ca-certificates-2021 | 139 KB    | : 100% 1.0/1 [00:00<00:00, 22.89it/s]
    gdcm-2.8.9           | 3.4 MB    | : 100% 1.0/1 [00:00<00:00,  1.42it/s]
    openjpeg-2.3.1       | 470 KB    | : 100% 1.0/1 [00:00<00:00,  6.52it/s]
    conda-4.11.0         | 16.9 MB   | : 100% 1.0/1 [00:04<00:00,  4.06s/it]
    libgcc-ng-11.2.0     | 906 KB    | : 100% 1.0/1 [00:00<00:00,  5.03it/s]
    libpng-1.6.37        | 306 KB    | : 100% 1.0/1 [00:00<00:00,  5.09it/s]
    _openmp_mutex-4.5    | 22 KB     | : 100% 1.0/1 [00:00<00:00, 26.27it/s]
    libtiff-4.0.9        | 566 KB    | : 100% 1.0/1 [00:00<00:00,  6.06it/s]
    certifi-2021.10.8    | 145 KB    | : 100% 1.0/1 [00:00<00:00, 19.71it/s]
    openssl-1.1.1l       | 2.1 MB    | : 100% 1.0/1 [00:00<00:00,  2.75it/s]
    json-c-0.13.1        | 76 KB     | : 100% 1.0/1 [00:00<00:00, 24.25it/s]
    Preparing transaction: / done
    Verifying transaction: \ | done
    Executing transaction: - \ done
    Collecting pydicom==2.0.0
      Downloading pydicom-2.0.0-py3-none-any.whl (35.4 MB)
         |████████████████████████████████| 35.4 MB 74 kB/s
    Installing collected packages: pydicom
    Successfully installed pydicom-2.0.0
    Drive already mounted at /content/drive; to attempt to forcibly remount, call drive.mount("/content/drive", force_remount=True).

O segundo passo é usar a biblioteca 'pydicom' para abrir o arquivo dicom desejado. Esta lib retorna um objeto especial com todas as informações armazenadas dentro de um dicom. Para este notebook, usaremos um conjunto de arquivos dicom extraídos do RSNA Pulmonary Embolism Detection Challenge, que estão armazenados na pasta que compartilhamos.

```python
import pydicom

DATASET_FOLDER = 'drive/MyDrive/Curso IA para Medicina - Cientista de Dados/1. Introdução Imagens Médicas/Dicom Hands-On/sample_train/'
dcm_file = DATASET_FOLDER + '1ac673a65484/43e3fab0e6a7/5fe509226d61.dcm'
dcm = pydicom.dcmread(dcm_file)
print(dcm)
```

    Dataset.file_meta -------------------------------
    (0002, 0010) Transfer Syntax UID                 UI: Implicit VR Little Endian
    -------------------------------------------------
    (0008, 0005) Specific Character Set              CS: 'ISO_IR 100'
    (0008, 0008) Image Type                          CS: "['ORIGINAL', 'PRIMARY', 'AXIAL']"
    (0008, 0016) SOP Class UID                       UI: 80e30f500244
    (0008, 0018) SOP Instance UID                    UI: 5fe509226d61
    (0008, 0060) Modality                            CS: 'CT'
    (0018, 0050) Slice Thickness                     DS: "1.25"
    (0018, 0060) KVP                                 DS: "120.0"
    (0018, 1120) Gantry/Detector Tilt                DS: "0.0"
    (0018, 1130) Table Height                        DS: "153.5"
    (0018, 1140) Rotation Direction                  CS: 'CW'
    (0018, 1151) X-Ray Tube Current                  IS: "367"
    (0018, 1152) Exposure                            IS: "3"
    (0018, 1210) Convolution Kernel                  SH: 'STANDARD'
    (0018, 5100) Patient Position                    CS: 'FFS'
    (0020, 000d) Study Instance UID                  UI: 1ac673a65484
    (0020, 000e) Series Instance UID                 UI: 43e3fab0e6a7
    (0020, 0011) Series Number                       IS: "2"
    (0020, 0013) Instance Number                     IS: "141"
    (0020, 0032) Image Position (Patient)            DS: [-175.400, -192.500, -176.500]
    (0020, 0037) Image Orientation (Patient)         DS: [1.000000, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000]
    (0020, 0052) Frame of Reference UID              UI: 7e544ca6e059
    (0028, 0002) Samples per Pixel                   US: 1
    (0028, 0004) Photometric Interpretation          CS: 'MONOCHROME2'
    (0028, 0010) Rows                                US: 512
    (0028, 0011) Columns                             US: 512
    (0028, 0030) Pixel Spacing                       DS: [0.751953, 0.751953]
    (0028, 0100) Bits Allocated                      US: 16
    (0028, 0101) Bits Stored                         US: 16
    (0028, 0102) High Bit                            US: 15
    (0028, 0103) Pixel Representation                US: 1
    (0028, 1050) Window Center                       DS: "40.0"
    (0028, 1051) Window Width                        DS: "350.0"
    (0028, 1052) Rescale Intercept                   DS: "-1024.0"
    (0028, 1053) Rescale Slope                       DS: "1.0"
    (7fe0, 0010) Pixel Data                          OW: Array of 524288 elements

Aqui podemos ver o que está armazenado dentro de um arquivo dicom.

Por enquanto, vamos focar nossa atenção na estrela principal: a imagem real do exame. Esta imagem é armazenada no campo "Pixel Data". Como mencionamos anteriormente, pydicom lê um dicom e retorna um objeto especial com diferentes tags dicom. Cada uma dessas tags pode ser acessada como uma variável de objeto normal. Por exemplo, os dados de pixel podem ser acessados usando dcm.PixelData. No entanto, o atributo PixelData armazena os bytes brutos usados para armazenar os pixels da imagem. Existe outro atributo especial que converte o PixelData para um formato mais amigável: o dcm.pixel_array.

Para este primeiro exemplo, usaremos um arquivo dicom de tomografia computadorizada. Portanto, esta imagem representa uma única fatia de um exame 3D. Mas, por enquanto, vamos nos concentrar apenas em como lidar com uma única fatia.

```python
import matplotlib.pyplot as plt
import numpy as np

img = dcm.pixel_array
print(f'min max img value = ({np.min(img)}, {np.max(img)})')
print(f'img shape = {img.shape}')
imgplot = plt.imshow(img, cmap='gray')
```

**Hounsfield Unit**

Como podemos ver na célula anterior, o pixel_array armazena os valores dos pixels no exame. Observe que, neste caso, os valores de pixel variam de -2000 a 4095 (nesta imagem). Nesta parte, mostramos que cada voxel (voxel é um pixel em um espaço 3D) em uma tomografia computadorizada indica a densidade daquela parte específica do corpo, de forma semelhante a um exame de raio-x. Portanto, valores de pixel mais altos indicam regiões de baixa densidade. Essa medida é realizada com a escala Hounsfield Unit (HU), usada para medir a radiodensidade. Nesta escala, a água destilada tem uma medida de 0 HU, enquanto o ar costuma ficar em torno de -1000 HU. Quando convertemos isso em uma imagem, as regiões de baixa densidade ficam mais escuras, enquanto as áreas de alta densidade são mais claras. Na dicom mostrada na célula anterior, podemos ver um corte mostrando parte dos pulmões do paciente. Os pulmões estão cheios de ar, diminuindo sua densidade. Por isso, é mostrado na imagem com um tom mais escuro.

Mas, na realidade, os arquivos dicom geralmente armazenam a matriz de pixels em uma representação interna. Na verdade, requer uma conversão especial para transformar o valor armazenado na escala de unidade desejada (HU no caso de um exame de TC). Para isso, precisamos de duas outras tags dicom: RescaleSlope e RescaleIntercept. A imagem HU é obtida pela seguinte operação:

\begin{align}
I_{HU} = I r_{s} + r_{i}
\end{align}

onde IHU é a imagem em escala HU, I é a imagem armazenada na matriz de pixels, rs é a etiqueta de inclinação de reescalonamento e ri é a interceptação de reescalonamento

```python
img = dcm.pixel_array

slope = float(dcm.RescaleSlope)
intercept = float(dcm.RescaleIntercept)
print(f'slope = {slope}')
print(f'intercept = {intercept}')

img = (img*slope +intercept)
print(f'min max img value = ({np.min(img)}, {np.max(img)})')
print(f'img shape = {img.shape}')
imgplot = plt.imshow(img, cmap='gray')
```

Ao trabalhar com imagens e aprendizado profundo, uma boa coisa a fazer é usar apenas imagens normalizadas. Para imagens de TC, por exemplo, sempre podemos converter uma imagem dicom em um intervalo normalizado entre (0, 1) sem perder nenhuma informação útil:

```python
def change_range(img, new_min, new_max, actual_min=None, actual_max=None):
    if actual_min is None or actual_max is None:
        actual_min = np.min(img)
        actual_max = np.max(img)

    if actual_min == new_min and actual_max == new_max:
        return img

    img = (
        (new_max - new_min) * (img - actual_min) / (actual_max - actual_min)
    ) + new_min

    return img

img = change_range(dcm.pixel_array, new_min=0.0, new_max=1.0)
print(f'min max img value = ({np.min(img)}, {np.max(img)})')
print(f'img shape = {img.shape}')
imgplot = plt.imshow(img, cmap='gray')
```

**Dicom Windowing Operation**

Uma imagem dicom de um exame de TC ou raio-X são todas representadas na escala da Unidade Hounsfield, que indica a densidade de cada região do corpo. Isso resulta em imagens com muita informação, geralmente representadas por pixels com 12 a 16 bits. Isso é muita informação. Imagens regulares são geralmente representadas com pixels de 8 bits (valores entre (0, 255)). Então, como podemos converter uma imagem dicom medida em HU em uma imagem comum? Bem, já fizemos isso na célula anterior: podemos simplesmente converter esta imagem para um intervalo diferente. Mas ao fazer isso, a imagem se torna uma imagem de baixo contraste, pois há muita informação para nossos olhos capturarem completamente. Uma abordagem mais sofisticada é usar janelas dicom.

Uma janela dicom indica qual faixa do espectro de imagem HU original queremos focar. Uma janela é definida pelos parâmetros principais:

Centro da Janela ( wc ): representa a faixa média de HU a focar;
Largura da janela ( ww ): indica a faixa de HU a partir do centro da janela a ser analisada.
A imagem em janela é calculada de acordo com a seguinte equação:

\begin{align}
min_{p} = w_c - \frac{w_w}{2} \\
max_{p} = w_c + \frac{w_w}{2} \\
I_w = \texttt{clip}(I, min_{p}, max_{p})
\end{align}

onde minp representa o valor mínimo de pixel da imagem em janela, maxp indica o valor máximo de pixel, I é a imagem HU original, Iw é a imagem em janela e clip(i,m,M) é uma função de recorte que recorta todos os valores dentro imagem i para um valor mínimo de m e um valor máximo de M, ou seja, cada pixel com um valor maior que M é recortado em M e todos os valores menores que m são recortados em m.

```python
slope = float(dcm.RescaleSlope)
intercept = float(dcm.RescaleIntercept)
window_center = float(dcm.WindowCenter)
window_width = float(dcm.WindowWidth)
print(f'slope = {slope}')
print(f'intercept = {intercept}')
print(f'window_center = {window_center}')
print(f'window_width = {window_width}')

img = dcm.pixel_array
img = (img*slope +intercept)
img_min = window_center - window_width//2
img_max = window_center + window_width//2
img = np.clip(img, img_min, img_max)

print(f'min max img value = ({np.min(img)}, {np.max(img)})')
imgplot = plt.imshow(img, cmap='gray')

```

**Building a Compact Windowing Function**

Vamos agora construir uma função compacta capaz de realizar uma operação de janelas sobre uma imagem dicom. Esta função nos permitirá reutilizar esta operação no restante deste curso. Também podemos testar diferentes valores de janela para ver o que muda.

Em primeiro lugar, devemos carregar o arquivo dicom. Já mostramos como carregar um arquivo dicom usando pydicom. Em alguns casos, o atributo de matriz de pixels pode ser compactado dentro do arquivo dicom. Para descompactá-lo, é importante usar a função interna descompactar. Existem vários algoritmos de compactação usados para arquivos dicom. O Pydicom tem alguns algoritmos de descompressão implementados, mas não todos. Para disponibilizar o número máximo de algoritmos de descompressão, recomendamos instalar a biblioteca gdcm (use a versão conda desta biblioteca, pois é mais fácil fazê-la funcionar com a biblioteca pydicom). Se estiver instalado, a função de descompressão funcionará com uma gama mais ampla de algoritmos de descompressão. Usar isso pode salvar seu futuro aprendizado profundo para o pipeline de inferência de imagens médicas.

```python
import gdcm

def read_dicom(dicom_path):
  ds = pydicom.dcmread(dicom_path)
  ds.decompress()
  return ds
```

Vamos agora construir uma função para ler as tags dicom de inclinação, interceptação e janela. Como vimos, podemos simplesmente ler essas tags e convertê-las em float. No entanto, isso pode falhar em alguns casos, onde essas tags são armazenadas como uma matriz. Portanto, usamos a seguinte função para recuperar esses valores (função recuperada deste post em uma competição do kaggle):

```python
def get_first_of_dicom_field_as_int(x):
  if type(x) == pydicom.multival.MultiValue:
    return int(x[0])
  else:
    return int(x)
```

Agora podemos construir efetivamente nossa função de janelas. Primeiro, devemos carregar o arquivo dicom usando nossa função read_dicom. A segunda coisa que nossa função de janela deve verificar é como os bits são armazenados na imagem dicom. Isso pode ser verificado usando a tag dicom PhotometricInterpretation, que mostra se os valores altos de pixel são convertidos em preto (MONOCHROME1) ou branco (MONOCHROME2). Para mais informações, consulte este e este link. Basicamente, vamos considerar aqui que MONOCHROME2 é o padrão básico a ser seguido, então se alguma dicom for MONOCHROME1, iremos convertê-la para MONOCHROME2 invertendo seu valor.

O restante da função usa conceitos já explorados neste caderno. Se quisermos um conjunto específico de parâmetros de janela, podemos passar esses valores como parâmetros para a função. Caso contrário, usaremos os parâmetros de janela padrão presentes no arquivo dicom.

```python
def get_single_window_img(path, window_center=None, window_width=None):
  dicom = read_dicom(path)
  img = dicom.pixel_array
  if 'MONOCHROME1' in dicom.PhotometricInterpretation:
    img = 2**dicom.BitsStored-img

  try:
    slope = get_first_of_dicom_field_as_int(dicom.RescaleSlope)
    intercept = get_first_of_dicom_field_as_int(dicom.RescaleIntercept)
    if window_center is None:
      window_center = get_first_of_dicom_field_as_int(dicom.WindowCenter)
      window_width = get_first_of_dicom_field_as_int(dicom.WindowWidth)

    img = (img*slope +intercept)
    img_min = window_center - window_width//2
    img_max = window_center + window_width//2
    img[imgimg_max] = img_max

    img = (img - img_min) / window_width
  except:
    return None

  return img
```

**Testing Other Window Parameters**

Com nossa função construída, podemos usá-la para testar diferentes parâmetros de janela. Cada parâmetro de janela é usado para focar a atenção em detalhes específicos da imagem dicom. Por exemplo, o par (centro da janela, largura da janela) usado para analisar os pulmões é (-600, 1500), enquanto uma janela específica do fígado é dada por (30, 150) e uma janela do osso da coluna é (400, 1800)

```python
img_lung = get_single_window_img(dcm_file, window_center=-600, window_width=1500)
img_liver = get_single_window_img(dcm_file, window_center=30, window_width=150)
img_spine = get_single_window_img(dcm_file, window_center=400, window_width=1800)

f, axarr = plt.subplots(1, 3, figsize=(15,15))
axarr[0].imshow(img_lung, cmap='gray')
axarr[1].imshow(img_liver, cmap='gray')
axarr[2].imshow(img_spine, cmap='gray')
```

Também podemos empilhar essas imagens obtidas usando diferentes parâmetros de janela em uma única imagem. Precisamos apenas adicionar cada imagem a um canal de cor diferente para obter um rgb

```python
img = np.stack([img_lung, img_liver, img_spine], axis=-1)
print(img.shape)
imgplot = plt.imshow(img)
```

Agora podemos encapsular essa operação de construir uma imagem dicom multicanal com diferentes parâmetros de janela em cada canal. Para isso, vamos construir uma função que recebe o caminho do arquivo dicom, uma lista de parâmetros de centro e largura da janela (neste caso, essas listas devem ter o mesmo comprimento), ou um único parâmetro de centro e largura da janela em caso queiramos uma imagem de canal único, ou um valor nulo para ambos os parâmetros caso queiramos carregar os parâmetros originais da janela do dicom.

```python
def get_dicom_img(path, window_center=None, window_width=None):
  img = None
  if window_center is None or window_width is None:
    img = get_single_window_img(path)
  elif type(window_center) == list:
    img = []
    for i in range(len(window_center)):
      img_ch = get_single_window_img(path, window_center[i], window_width[i])
      img.append(img_ch)
    img = np.array(img)
    img = np.moveaxis(img, 0,2)
  else:
    img = get_single_window_img(path, window_center, window_width)

  return img

window_center_list = [-600, 30, 400]
window_width_list = [1500, 150, 1800]
img_multi = get_dicom_img(dcm_file, window_center_list, window_width_list)
img_lung = get_dicom_img(dcm_file, -600, 1500)
img_original = get_dicom_img(dcm_file)

f, axarr = plt.subplots(1, 3, figsize=(15,15))
print(img_original.shape)
axarr[0].imshow(img_multi)
axarr[1].imshow(img_lung, cmap='gray')
axarr[2].imshow(img_original, cmap='gray')
```


```python
import os
os.environ['TRKXINPUTDIR']="/global/cfs/cdirs/m3443/data/trackml-kaggle/train_10evts"
input_data_path = "/global/cfs/projectdirs/m3443/usr/caditi97/iml2021/run_dir"
os.environ['TRKXOUTPUTDIR']= input_data_path
```

```python
import pkg_resources
import yaml
import pprint
import random
random.seed(1234)
import numpy as np
# import pandas as pd
import itertools
import matplotlib.pyplot as plt
import tqdm
from os import listdir
from os.path import isfile, join
import matplotlib.cm as cm
import sys
import tqdm
from tqdm import tqdm
import tqdm.notebook as tq
# import sympy
# from sympy import S, symbols, printing
# %matplotlib widget

sys.path.append('/global/homes/c/caditi97/exatrkx-iml2020/exatrkx/src/')

# 3rd party
import torch
import torch.nn.functional as F
from torch_geometric.data import Data
from trackml.dataset import load_event
from pytorch_lightning import Trainer
from pytorch_lightning.callbacks import ModelCheckpoint
from pytorch_lightning.loggers.neptune import NeptuneLogger

# local import
from exatrkx import config_dict # for accessing predefined configuration files
from exatrkx import outdir_dict # for accessing predefined output directories
from exatrkx.src import utils_dir
from exatrkx.src import utils_robust
from utils_robust import *

# for preprocessing
from exatrkx import FeatureStore
from exatrkx.src import utils_torch

# for embedding
from exatrkx import LayerlessEmbedding
from exatrkx import EmbeddingInferenceCallback
from exatrkx.src import utils_torch
from torch_cluster import radius_graph
from utils_torch import build_edges
from embedding.embedding_base import *

# for filtering
from exatrkx import VanillaFilter

# for GNN
import tensorflow as tf
from graph_nets import utils_tf
from exatrkx import SegmentClassifier
import sonnet as snt

# for labeling
from exatrkx.scripts.tracks_from_gnn import prepare as prepare_labeling
from exatrkx.scripts.tracks_from_gnn import clustering as dbscan_clustering

# track efficiency
from trackml.score import _analyze_tracks
from exatrkx.scripts.eval_reco_trkx import make_cmp_plot, pt_configs, eta_configs
from functools import partial

```

```python
mypath = "/global/cfs/projectdirs/m3443/usr/caditi97/iml2021/run_dir/fs_notscaled"
```

```python
events = [f for f in listdir(mypath)]
```

```python
for evtid in tqdm(events):
    f = join(mypath,evtid)
    data = torch.load(f)
    x = torch.from_numpy(data.x.numpy()/np.array([3000, np.pi, 400])).float()
    new_data = Data(event_file=data.event_file,
                    x=x,
                    pid=data.pid,
                    layers=data.layers,
                    hid=data.hid,
                   layerless_true_edges=data.layerless_true_edges)
    filename = f"/global/cfs/projectdirs/m3443/usr/caditi97/iml2021/run_dir/feature_store/{evtid}"
    with open(filename, 'wb') as pickle_file:
            torch.save(new_data, pickle_file)
```

    100%|██████████| 5000/5000 [00:28<00:00, 176.04it/s]

```python
torch.load(filename)
# tf.convert_to_tensor(data_np, np.float32)
```

    Data(event_file="WmuHNL15GeV_NoPileUp_Generic/event000004814", hid=[201], layerless_true_edges=[2, 183], layers=[201], pid=[201], x=[201, 3])

```python

```