.. _csd:

CSD-1000R
#########

This dataset, intended for model testing, contains the SOAP power spectrum
features and local NMR chemical shieldings for 100 environments selected
from CSD-1000r, originally published in [Ceriotti2019]_.

Function Call
-------------

.. function:: skcosmo.datasets.load_csd_1000r

Data Set Characteristics
------------------------

    :Number of Instances: Each representation 100

    :Number of Features: Each representation 100

    The representations were computed with [C1]_ using the hyperparameters:

    :rascal hyperparameters:

    +---------------------------+------------+
    | key                       |   value    |
    +---------------------------+------------+
    | interaction_cutoff:       |    3.5     |
    +---------------------------+------------+
    | max_radial:               |      6     |
    +---------------------------+------------+
    | max_angular:              |      6     |
    +---------------------------+------------+
    | gaussian_sigma_constant": |     0.4    |
    +---------------------------+------------+
    | gaussian_sigma_type:      |  "Constant"|
    +---------------------------+------------+
    | cutoff_smooth_width:      |     0.5    |
    +---------------------------+------------+
    | normalize:                |    True    |
    +---------------------------+------------+

    Of the 2'520 resulting features, 100 were selected via FPS using [C2]_.

References
----------

   .. [C1] https://github.com/cosmo-epfl/librascal commit e78f1c69
   .. [C2] https://github.com/cosmo-epfl/scikit-cosmo commit 64e789f

Reference Code
--------------

.. code-block:: python

  import numpy as np
  from ase.io import read

  from skcosmo.feature_selection import SimpleFPS
  from rascal.representations import SphericalInvariants as SOAP


  # read all of the frames and book-keep the centers and species
  filename = "/path/to/CSD-1000r.xyz"
  frames = np.asarray(
      read(filename, ":"),
      dtype=object,
  )

  n_centers = [len(frame) for frame in frames]
  n_env_accum = [sum(n_centers[: i + 1]) for i in range(len(n_centers))]
  n_env = sum(n_centers)

  numbers = np.concatenate([frame.numbers for frame in frames])
  number_loc = np.array([np.where(numbers == i)[0] for i in [1, 6, 7, 8]], dtype=object)


  # compute radial soap vectors as first pass
  hypers = dict(
      soap_type="PowerSpectrum",
      interaction_cutoff=3.5,
      max_radial=6,
      max_angular=0,
      gaussian_sigma_type="Constant",
      gaussian_sigma_constant=0.4,
      cutoff_smooth_width=0.5,
  )
  soap = SOAP(**hypers)
  X_raw = soap.transform(frames).get_features(soap)


  # select 100 diverse samples
  i_selected = SimpleFPS(n_features_to_select=100).fit(X_raw.T).selected_idx_

  # book-keep which frames these samples belong in
  frames_select = [np.where(n_env_accum > i)[0][0] for i in i_selected]
  reduced_frames_select = list(sorted(set(frames_select)))

  properties_select = [
      frame.arrays["CS_local"] for frame in frames[reduced_frames_select]
  ]

  n_centers_select = [len(frame) for frame in frames[reduced_frames_select]]
  n_env_accum_select = [
      sum(n_centers_select[: i + 1]) for i in range(len(n_centers_select))
  ]
  n_env_select = sum(n_centers_select)


  # compute a larger power spectrum for these frames
  hypers["max_angular"] = 6
  soap_select = SOAP(**hypers)
  X_raw_select = soap_select.transform(frames[reduced_frames_select]).get_features(
      soap_select
  )


  # pull the soap vectors only pertaining to the selected environments
  i_select_reduced = []
  properties_select_reduced = np.zeros(len(i_selected), dtype=float)
  for i in range(len(i_selected)):
      my_orig_frame = frames_select[i]
      my_frame = reduced_frames_select.index(my_orig_frame)
      if my_orig_frame != 0:
          orig_loc = i_selected[i] - n_env_accum[my_orig_frame - 1]
          new_loc = orig_loc + n_env_accum_select[my_frame - 1]
      else:
          orig_loc = i_selected[i]
          new_loc = i_selected[i]
      i_select_reduced.append(new_loc)
      properties_select_reduced[i] = frames[my_orig_frame].arrays["CS_local"][orig_loc]

  X_sample_select = X_raw_select[i_select_reduced]


  # select 100 / 2520 soap features
  n_select = 100
  X_select = SimpleFPS(n_features_to_select=n_select).fit_transform(X_sample_select)
  Y_select = properties_select_reduced.reshape(-1, 1)

  data = dict(X=X_select, Y=Y_select)
  np.savez("skcosmo/datasets/data/csd-1000r.npz", **data)
