cta-observatory / dl1-data-handler

DL1 HDF5 format IACT data writer + reader + processor
MIT License
11 stars 18 forks source link

dl1_data_handler_demo.ipynb: "ValueError: ndarray is not C-contiguous" #71

Closed riwim closed 4 years ago

riwim commented 5 years ago

Hi all,

I try to run the DL1 Data Handler Demo notebook. I have installed ctapipe as described there and dl1dh as described here by pip. When I execute data_writer.process_data(runlist) of the demo notebook I get the following error:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-10-47301b29a123> in <module>
----> 1 data_writer.process_data(runlist)

/home/user/dl1-data-handler_0.8.0/dl1_data_handler/writer.py in process_data(self, run_list)
    812             for run in run_list:
    813                 logger.info("Starting run for target: {}...".format(run['target']))
--> 814                 self._process_data(run['inputs'], run['target'])
    815 
    816         logger.info("Done!")

/home/user/dl1-data-handler_0.8.0/dl1_data_handler/writer.py in _process_data(self, file_list, output_filename)
    886             # Write all events sequentially
    887             for event in event_source:
--> 888                 self.calibrator.calibrate(event)
    889                 self.combine_channels(event)
    890                 if (self.preselection_cut_function is not None and not

/scratch/user/envs/ctapipe_dl1dh/lib/python3.7/site-packages/ctapipe/calib/camera/calibrator.py in calibrate(self, event)
    120         self.r1.calibrate(event)
    121         self.dl0.reduce(event)
--> 122         self.dl1.calibrate(event)

/scratch/user/envs/ctapipe_dl1dh/lib/python3.7/site-packages/ctapipe/calib/camera/dl1.py in calibrate(self, event)
    211                         e = self.extractor
    212                         g = event.inst.subarray.tel[telid].camera
--> 213                         e.neighbours = g.neighbor_matrix_where
    214                     extract = self.extractor.extract_charge
    215                     charge, peakpos, window = extract(cleaned)

/scratch/user/envs/ctapipe_dl1dh/lib/python3.7/site-packages/astropy/utils/decorators.py in __get__(self, obj, owner)
    742                 return val
    743             else:
--> 744                 val = self.fget(obj)
    745                 obj.__dict__[self._key] = val
    746                 return val

/scratch/user/envs/ctapipe_dl1dh/lib/python3.7/site-packages/ctapipe/instrument/camera.py in neighbor_matrix_where(self)
    392         ndarray
    393         """
--> 394         return np.ascontiguousarray(np.array(np.where(self.neighbor_matrix)).T)
    395 
    396     @lazyproperty

/scratch/user/envs/ctapipe_dl1dh/lib/python3.7/site-packages/astropy/utils/decorators.py in __get__(self, obj, owner)
    742                 return val
    743             else:
--> 744                 val = self.fget(obj)
    745                 obj.__dict__[self._key] = val
    746                 return val

/scratch/user/envs/ctapipe_dl1dh/lib/python3.7/site-packages/ctapipe/instrument/camera.py in neighbor_matrix(self)
    376     @lazyproperty
    377     def neighbor_matrix(self):
--> 378         return _neighbor_list_to_matrix(self.neighbors)
    379 
    380     @lazyproperty

/scratch/user/envs/ctapipe_dl1dh/lib/python3.7/site-packages/astropy/utils/decorators.py in __get__(self, obj, owner)
    742                 return val
    743             else:
--> 744                 val = self.fget(obj)
    745                 obj.__dict__[self._key] = val
    746                 return val

/scratch/user/envs/ctapipe_dl1dh/lib/python3.7/site-packages/ctapipe/instrument/camera.py in neighbors(self)
    369             self.pix_x.value,
    370             self.pix_y.value,
--> 371             rad=1.4 * dist.value
    372         )
    373 

/scratch/user/envs/ctapipe_dl1dh/lib/python3.7/site-packages/ctapipe/instrument/camera.py in _find_neighbor_pixels(pix_x, pix_y, rad)
    685     indices = np.arange(len(pix_x))
    686     kdtree = KDTree(points)
--> 687     neighbors = [kdtree.query_ball_point(p, r=rad) for p in points]
    688     for nn, ii in zip(neighbors, indices):
    689         nn.remove(ii)  # get rid of the pixel itself

/scratch/user/envs/ctapipe_dl1dh/lib/python3.7/site-packages/ctapipe/instrument/camera.py in <listcomp>(.0)
    685     indices = np.arange(len(pix_x))
    686     kdtree = KDTree(points)
--> 687     neighbors = [kdtree.query_ball_point(p, r=rad) for p in points]
    688     for nn, ii in zip(neighbors, indices):
    689         nn.remove(ii)  # get rid of the pixel itself

ckdtree.pyx in scipy.spatial.ckdtree.cKDTree.query_ball_point()

/scratch/user/envs/ctapipe_dl1dh/lib/python3.7/site-packages/scipy/spatial/ckdtree.cpython-37m-x86_64-linux-gnu.so in View.MemoryView.memoryview_cwrapper()

/scratch/user/envs/ctapipe_dl1dh/lib/python3.7/site-packages/scipy/spatial/ckdtree.cpython-37m-x86_64-linux-gnu.so in View.MemoryView.memoryview.__cinit__()

ValueError: ndarray is not C-contiguous

Any ideas what I could do?

Edit: I also tried to install dl1_data_handler with the described conda method. I get the same error.

kosack commented 5 years ago

are you using the development (master) version of ctapipe, or the v0.6.2 release? With the master/dev version, the gain selection is done automatically, so there is no need for the combine_channels() call, and that may be corrupting the data. If it's the stable release version, it's strange.

vuillaut commented 5 years ago

are you using the development (master) version of ctapipe, or the v0.6.2 release? With the master/dev version, the gain selection is done automatically, so there is no need for the combine_channels() call, and that may be corrupting the data. If it's the stable release version, it's strange.

dl1_data_handler is based on ctapipe v0.6.2 release.

kosack commented 5 years ago

Yes the question is whether @riwim installed it via conda (so it's v0.6.2) or following the development instructions (in which case it is a pre-release of v0.7, and will not work without modifications to dl1-data-handler).

kosack commented 5 years ago

try running ctapipe-info --version and paste the result here.

If it is v0.6.2 only, it's fine, if it says something like:

version: 0.6.2.post170+git82fa697

then it is too new a version (e.g. 170 commits past v0.6.2)

riwim commented 5 years ago

Thanks for looking at this issue!

The asked results

$ ctapipe-info --version
*** ctapipe version info ***
version: 0.6.2

Full procedure

At the moment it seems that I get different errors (current error at the end). To make it more reproducable I just tried to install again and documented my full procedure:

$ conda create -n dl1dh_2019-07-09 python=3.6
(...)

The following NEW packages will be INSTALLED:

    ca-certificates: 2019.6.16-hecc5488_0 conda-forge
    certifi:         2019.6.16-py36_0     conda-forge
    libffi:          3.2.1-he1b5a44_1006  conda-forge
    libgcc-ng:       9.1.0-hdf63c60_0     anaconda
    libstdcxx-ng:    9.1.0-hdf63c60_0     anaconda
    ncurses:         6.1-hf484d3e_1002    conda-forge
    openssl:         1.1.1b-h14c3975_1    conda-forge
    pip:             19.1.1-py36_0        conda-forge
    python:          3.6.7-h357f687_1005  conda-forge
    readline:        8.0-hf8c457e_0       conda-forge
    setuptools:      41.0.1-py36_0        conda-forge
    sqlite:          3.28.0-hcee41ef_1    conda-forge
    tk:              8.6.9-hed695b0_1002  conda-forge
    wheel:           0.33.4-py36_0        conda-forge
    xz:              5.2.4-h14c3975_1001  conda-forge
    zlib:            1.2.11-h14c3975_1004 conda-forge

$ conda activate dl1dh_2019-07-09

$ conda config --add channels anaconda
Warning: 'anaconda' already in 'channels' list, moving to the top

$ conda config --add channels cta-observatory
Warning: 'cta-observatory' already in 'channels' list, moving to the top

$ conda config --add channels anaconda
Warning: 'anaconda' already in 'channels' list, moving to the top

$ conda install -c bryankim96 dl1_data_handler
The following NEW packages will be INSTALLED:                 

    astropy:            3.2.1-py37h7b6447c_0   anaconda       
    atomicwrites:       1.3.0-py37_1           anaconda       
    attrs:              19.1.0-py37_1          anaconda       
    blas:               1.0-mkl                anaconda       
    blosc:              1.16.3-he1b5a44_1      conda-forge    
    bzip2:              1.0.6-h14c3975_5       anaconda       
    cairo:              1.14.12-h8948797_3     anaconda       
    cloudpickle:        1.2.1-py_0             anaconda       
    corsikaio:          0.2.0-pyh1d22016_0     cta-observatory
    ctapipe:            0.6.2-py37ha8d69ae_2   cta-observatory
    ctapipe-extra:      0.2.17-0               cta-observatory
    cycler:             0.10.0-py37_0          anaconda       
    cython:             0.29.11-py37he6710b0_0 anaconda       
    cytoolz:            0.9.0.1-py37h14c3975_1 anaconda       
    dask-core:          2.0.0-py_0             anaconda       
    dbus:               1.13.6-h746ee38_0      anaconda       
    decorator:          4.4.0-py37_1           anaconda       
    dl1_data_handler:   0.7.4-py37_0           bryankim96      
    eventio:            0.11.0-py37h39e3cac_0  cta-observatory 
    expat:              2.2.6-he6710b0_0       anaconda        
    fontconfig:         2.13.0-h9420a91_0      anaconda        
    freetype:           2.9.1-h8a8886c_1       anaconda        
    fribidi:            1.0.5-h7b6447c_0       anaconda        
    glib:               2.56.2-hd408876_0      anaconda        
    graphite2:          1.3.13-h23475e2_0      anaconda        
    graphviz:           2.40.1-h21bd128_2      anaconda        
    gst-plugins-base:   1.14.0-hbbd80ab_1      anaconda        
    gstreamer:          1.14.0-hb453b48_1      anaconda        
    harfbuzz:           1.8.8-hffaf4a1_0       anaconda        
    hdf5:               1.10.4-hb1b8bf9_0      anaconda        
    icu:                58.2-h211956c_0        anaconda        
    imageio:            2.5.0-py37_0           anaconda        
    iminuit:            1.3.3-py37h962f231_0   anaconda        
    importlib_metadata: 0.17-py37_1            anaconda        
    intel-openmp:       2019.4-243             anaconda        
    ipython_genutils:   0.2.0-py37_0           anaconda        
    joblib:             0.13.2-py37_0          anaconda        
    jpeg:               9b-habf39ab_1          anaconda        
    kiwisolver:         1.1.0-py37he6710b0_0   anaconda        
    libgfortran-ng:     7.3.0-hdf63c60_0       anaconda        
    libpng:             1.6.37-hbc83047_0      anaconda        
    libsodium:          1.0.16-h1bed415_0      anaconda        
    libtiff:            4.0.10-h2733197_2      anaconda        
    libuuid:            1.0.3-h1bed415_2       anaconda        
    libxcb:             1.13-h1bed415_1        anaconda        
    libxml2:            2.9.9-hea5a465_1       anaconda        
    llvmlite:           0.29.0-py37hd408876_0  anaconda        
    lzo:                2.10-h1bfc0ba_1        anaconda        
    matplotlib:         3.1.0-py37h5429711_0   anaconda        
    mkl:                2019.4-243             anaconda        
    mkl-service:        2.0.2-py37h7b6447c_0   anaconda        
    mkl_fft:            1.0.12-py37ha843d7b_0  anaconda        
    mkl_random:         1.0.2-py37hd81dba3_0   anaconda        
    mock:               3.0.5-py37_0           anaconda        
    more-itertools:     7.0.0-py37_0           anaconda        
    networkx:           2.3-py_0               anaconda        
    numba:              0.44.1-py37h962f231_0  anaconda        
    numexpr:            2.6.9-py37h9e4a6bb_0   anaconda        
    numpy:              1.16.4-py37h7e9f1db_0  anaconda        
    numpy-base:         1.16.4-py37hde5b4d6_0  anaconda        
    olefile:            0.46-py37_0            anaconda        
    packaging:          19.0-py37_0            anaconda        
    pandas:             0.24.2-py37he6710b0_0  anaconda        
    pango:              1.42.4-h049681c_0      anaconda        
    pcre:               8.43-he6710b0_0        anaconda        
    pillow:             6.0.0-py37h34e0f95_0   anaconda        
    pixman:             0.38.0-h7b6447c_0      anaconda        
    pluggy:             0.12.0-py_0            anaconda        
    psutil:             5.6.3-py37h7b6447c_0   anaconda        
    py:                 1.8.0-py37_0           anaconda        
    pyhessio:           2.1.1-py37h39e3cac_1   cta-observatory 
    pyparsing:          2.4.0-py_0             anaconda        
    pyqt:               5.9.2-py37h22d08a2_1   anaconda        
    pytables:           3.5.2-py37h71ec239_1   anaconda        
    pytest:             5.0.0-py37_0           anaconda        
    pytest-arraydiff:   0.3-py37h39e3cac_0     anaconda                                          
    pytest-astropy:     0.5.0-py37_0           anaconda                                          
    pytest-doctestplus: 0.3.0-py37_0           anaconda                                          
    pytest-openfiles:   0.3.2-py37_0           anaconda                                          
    pytest-remotedata:  0.3.1-py37_0           anaconda                                          
    pytest-runner:      4.4-py_0               anaconda                                          
    python-dateutil:    2.8.0-py37_0           anaconda                                          
    pytz:               2019.1-py_0            anaconda                                          
    pywavelets:         1.0.3-py37hdd07704_1   anaconda                                          
    pyyaml:             5.1.1-py37h7b6447c_0   anaconda                                          
    pyzmq:              18.0.0-py37he6710b0_0  anaconda                                          
    qt:                 5.9.7-h5867ecd_1       anaconda                                          
    scikit-image:       0.15.0-py37he6710b0_0  anaconda                                          
    scikit-learn:       0.21.2-py37hd81dba3_0  anaconda                                          
    scipy:              1.2.1-py37h7c811a0_0   anaconda                                          
    sip:                4.19.13-py37he6710b0_0 anaconda                                          
    six:                1.12.0-py37_0          anaconda                                          
    toolz:              0.9.0-py37_0           anaconda                                          
    tornado:            6.0.3-py37h7b6447c_0   anaconda                                          
    tqdm:               4.32.1-py_0            anaconda                                          
    traitlets:          4.3.2-py37_0           anaconda                                          
    wcwidth:            0.1.7-py37_0           anaconda                                          
    yaml:               0.1.7-h96e3832_1       anaconda                                          
    zeromq:             4.3.1-he6710b0_3       anaconda                                          
    zipp:               0.5.1-py_0             anaconda                                          
    zstd:               1.3.7-h0b5b093_0       anaconda                                          

The following packages will be UPDATED:                                                          

    certifi:            2019.6.16-py36_0       conda-forge     --> 2019.6.16-py37_0 anaconda     
    openssl:            1.1.1b-h14c3975_1      conda-forge     --> 1.1.1-h7b6447c_0 anaconda     
    pip:                19.1.1-py36_0          conda-forge     --> 19.1.1-py37_0    anaconda     
    python:             3.6.7-h357f687_1005    conda-forge     --> 3.7.3-h33d41f4_1 conda-forge  
    setuptools:         41.0.1-py36_0          conda-forge     --> 41.0.1-py37_0    anaconda     
    wheel:              0.33.4-py36_0          conda-forge     --> 0.33.4-py37_0    anaconda     

The following packages will be DOWNGRADED:                                                       

    ca-certificates:    2019.6.16-hecc5488_0   conda-forge     --> 2019.5.15-0      anaconda             

$ git clone https://github.com/cta-observatory/dl1-data-handler.git    

$ cd dl1-data-handler

$ cat runlist_diffgammas.yml
- inputs:
    - '/full/path/to/gammas_diffuse/gamma_20deg_180deg_run10001___cta-prod3_desert-2150m-Paranal-merged_cone10.simtel.gz'
  target: 'diffuse_gammas.h5'

$ python scripts/write_data.py runlist_diffgammas.yml --debug
INFO:__main__:Number of input files in runlist: 1
INFO:__main__:Number of output files requested: 1
INFO:__main__:No config file provided, using default settings
INFO:dl1_data_handler.writer:Max output file size set at 10737418240 bytes. Note that this may increase the number of output files.
INFO:dl1_data_handler.writer:1 parallel processes requested.
INFO:dl1_data_handler.writer:Creating processes...
INFO:dl1_data_handler.writer:Starting processes...
INFO:dl1_data_handler.writer:Writing general header information to file attributes...
INFO:dl1_data_handler.writer:Creating array info table...
INFO:dl1_data_handler.writer:Writing array/subarray information to table...
INFO:dl1_data_handler.writer:Writing telescope type information to table...
INFO:dl1_data_handler.writer:Writing MC header information to file attributes...
INFO:dl1_data_handler.writer:Creating SST-ASTRI:ASTRICam image table...
INFO:dl1_data_handler.writer:Creating SST-1M:DigiCam image table...
INFO:dl1_data_handler.writer:Creating MST:FlashCam image table...
INFO:dl1_data_handler.writer:Creating MST:NectarCam image table...
INFO:dl1_data_handler.writer:Creating SST-GCT:CHEC image table...
INFO:dl1_data_handler.writer:Creating LST:LSTCam image table...
Process Process-1:
Traceback (most recent call last):
  File "/scratch/riwim/envs/dl1dh_2019-07-09/lib/python3.7/multiprocessing/process.py", line 297, in _bootstrap
    self.run()
  File "/scratch/riwim/envs/dl1dh_2019-07-09/lib/python3.7/multiprocessing/process.py", line 99, in run
    self._target(*self._args, **self._kwargs)
  File "/scratch/riwim/envs/dl1dh_2019-07-09/lib/python3.7/site-packages/dl1_data_handler/writer.py", line 870, in _process_data
    self.combine_channels(event)
  File "/scratch/riwim/envs/dl1dh_2019-07-09/lib/python3.7/site-packages/dl1_data_handler/writer.py", line 1001, in combine_channels
    combined_image, combined_peakpos = self.gain_selection(waveform, signals, peakpos, cam_id, self.gain_thresholds[cam_id])
  File "/scratch/riwim/envs/dl1dh_2019-07-09/lib/python3.7/site-packages/dl1_data_handler/writer.py", line 976, in gain_selection
    signal_mask = gain_mask.max(axis=1)
  File "/scratch/riwim/envs/dl1dh_2019-07-09/lib/python3.7/site-packages/numpy/core/_methods.py", line 28, in _amax
    return umr_maximum(a, axis, None, out, keepdims, initial)
numpy.AxisError: axis 1 is out of bounds for array of dimension 1
INFO:dl1_data_handler.writer:Adding indexed columns...
INFO:dl1_data_handler.writer:Added index on /Events:mc_energy
INFO:dl1_data_handler.writer:Added index on /Events:alt
INFO:dl1_data_handler.writer:Added index on /Events:az
INFO:dl1_data_handler.writer:Added index on /SSTASTRI_ASTRICam:event_index
INFO:dl1_data_handler.writer:Added index on /SST1M_DigiCam:event_index
INFO:dl1_data_handler.writer:Added index on /MST_FlashCam:event_index
INFO:dl1_data_handler.writer:Added index on /MST_NectarCam:event_index
INFO:dl1_data_handler.writer:Added index on /SSTGCT_CHEC:event_index
INFO:dl1_data_handler.writer:Added index on /LST_LSTCam:event_index
INFO:dl1_data_handler.writer:Done!
kosack commented 5 years ago

Thanks - seems it's a problem in dl1-data-handler then, and not ctapipe. Could have something to do with ASTRI telescopes - they do not return waveforms, so sometimes need special handling.

riwim commented 5 years ago

Of course I also tried to install via pip. Please notice that pip freeze returns ctapipe===unknown while ctapipe-info returns version: 0.8.0. Furthermore we now get a third error: KeyError: 'num_showers'

Full procedure - pip

$ git clone https://github.com/cta-observatory/dl1-data-handler.git

$ cd dl1-data-handler

$ virtualenv venv

$ source venv/bin/activate

$ pip install .

$ pip freeze
astropy==3.2.1
atomicwrites==1.3.0
attrs==19.1.0
bokeh==1.2.0
corsikaio==0.2.0
coverage==4.5.3
ctapipe===unknown
ctapipe-extra==0.2.17
cycler==0.10.0
decorator==4.4.0
dl1-data-handler==0.8.0
eventio==0.21.2
iminuit==1.3.7
importlib-metadata==0.18
ipython-genutils==0.2.0
Jinja2==2.10.1
joblib==0.13.2
kiwisolver==1.1.0
llvmlite==0.29.0
MarkupSafe==1.1.1
matplotlib==3.1.1
mock==3.0.5
more-itertools==7.1.0
numba==0.44.1
numexpr==2.6.9
numpy==1.16.4
packaging==19.0
pandas==0.24.2
Pillow==6.1.0
pluggy==0.12.0
psutil==5.6.3
py==1.8.0
pyhessio==2.1.1
pyparsing==2.4.0
pytest==5.0.1
pytest-cov==2.7.1
pytest-runner==5.1
python-dateutil==2.8.0
pytz==2019.1
PyYAML==5.1.1
scikit-learn==0.21.2
scipy==1.3.0
six==1.12.0
tables==3.5.2
tornado==6.0.3
tqdm==4.32.2
traitlets==4.3.2
wcwidth==0.1.7
zipp==0.5.2

$ ctapipe-info --version
*** ctapipe version info ***
version: 0.8.0

$ python scripts/write_data.py runlist_diffgammas.yml --debug
INFO:__main__:Number of input files in runlist: 1
INFO:__main__:Number of output files requested: 1
INFO:__main__:No config file provided, using default settings
INFO:dl1_data_handler.writer:Max output file size set at 10737418240 bytes. Note that this may increase the number of output files.
INFO:dl1_data_handler.writer:1 parallel processes requested.
INFO:dl1_data_handler.writer:Creating processes...
INFO:dl1_data_handler.writer:Starting processes...
Process Process-1:
Traceback (most recent call last):
  File "/opt/anaconda/lib/python3.6/multiprocessing/process.py", line 258, in _bootstrap
    self.run()
  File "/opt/anaconda/lib/python3.6/multiprocessing/process.py", line 93, in run
    self._target(*self._args, **self._kwargs)
  File "/home/riwim/dl1dh_pip_2019-07-09/dl1-data-handler/venv/lib/python3.6/site-packages/dl1_data_handler/writer.py", line 881, in _process_data
    example_event = next(event_source._generator())
  File "/home/riwim/dl1dh_pip_2019-07-09/dl1-data-handler/venv/lib/python3.6/site-packages/ctapipe/io/simteleventsource.py", line 92, in _generator
    yield from self.__generator()
  File "/home/riwim/dl1dh_pip_2019-07-09/dl1-data-handler/venv/lib/python3.6/site-packages/ctapipe/io/simteleventsource.py", line 175, in __generator
    data.mcheader.num_showers = mc_run_head['num_showers']
KeyError: 'num_showers'
Exception ignored in: <bound method CTAMLDataDumper.__del__ of <dl1_data_handler.writer.CTAMLDataDumper object at 0x7f1f45621c50>>
Traceback (most recent call last):
  File "/home/riwim/dl1dh_pip_2019-07-09/dl1-data-handler/venv/lib/python3.6/site-packages/dl1_data_handler/writer.py", line 208, in __del__
    self.file.root.Events.flush()
  File "/home/riwim/dl1dh_pip_2019-07-09/dl1-data-handler/venv/lib/python3.6/site-packages/tables/group.py", line 839, in __getattr__
    return self._f_get_child(name)
  File "/home/riwim/dl1dh_pip_2019-07-09/dl1-data-handler/venv/lib/python3.6/site-packages/tables/group.py", line 711, in _f_get_child
    self._g_check_has_child(childname)
  File "/home/riwim/dl1dh_pip_2019-07-09/dl1-data-handler/venv/lib/python3.6/site-packages/tables/group.py", line 398, in _g_check_has_child
    % (self._v_pathname, name))
tables.exceptions.NoSuchNodeError: group ``/`` does not have a child named ``Events``
INFO:dl1_data_handler.writer:Done!
TjarkMiener commented 5 years ago

Hi @riwim! Sorry for the late reply (I hope is not too late for your project). We will be soon updating to ctapipe v0.7.0, which will basically solve the installation issues. In the meantime, you can install DL1DH on top of ctapipe by cloning the ctapipe repo and checking out to v0.6.2 (git checkout tags/v0.6.2). Then you can create an environment (conda env create -n ctapipe -f environment.yml) and install ctapipe with setup.py (python setup.py install). After that you can clone and install the DL1DH repo with (python setup.py install). Somehow it is not working with pip.