{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Step 2: Generate data samples"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    ":::{warning}\n",
    "\n",
    "The {doc}`pycompwa </index>` is no longer maintained. Use the [ComPWA](https://compwa-org.rtfd.io) packages [QRules](https://qrules.rtfd.io), [AmpForm](https://ampform.rtfd.io), and [TensorWaves](https://tensorwaves.rtfd.io) instead!\n",
    "\n",
    ":::"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In this section, we will use the amplitude model that we created with the expert system to generate a data sample via hit & miss Monte Carlo. This requires us to work with the User Interface to ComPWA, the C++ back-end of {mod}`pycompwa`."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2.1 Generate"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In the previous step, we created an amplitude module and exported it as an XML file. We now need to go through a few steps to generate a phase space sample and a data sample for the decay $J/\\psi \\rightarrow \\gamma\\pi^0\\pi^0$:\n",
    "\n",
    "1. Import the section of particle definitions that is embedded in the XML file.\n",
    "\n",
    "2. Build a {class}`.Kinematics` object following the specifications of the dynamics in the XML model file (in this case, the helicity formalism). The second argument of this function is a particle list.\n",
    "\n",
    "3. The information in the {class}`.Kinematics` instance is sufficient for generating a phase space sample. This sample defines the space on which to evaluate the intensities of the amplitude model.\n",
    "\n",
    "4. For generating a data sample, you require an {class}`.Intensity` profile for this specific decay. You can construct such an object from the model XML file using the {class}`.IntensityBuilderXML`. Because we want the intensities to be normalized, you have to pass the generated phase space sample as an argument to the intensity builder. Note that during the creation of the {class}`.Intensity` object, the {class}`.Kinematics` instance is updated with the subsystems required for the decay topology.\n",
    "\n",
    "Now all building blocks for generating our data sample are at hand and you can define a data sample of arbitrary size!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pycompwa.ui as pwa  # interface to ComPWA"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# specify kinematics\n",
    "particle_list = pwa.read_particles(\"model.xml\")\n",
    "kinematics = pwa.create_helicity_kinematics(\"model.xml\", particle_list)\n",
    "\n",
    "# specify generators\n",
    "generator = pwa.EvtGenGenerator(\n",
    "    kinematics.get_particle_state_transition_kinematics_info()\n",
    ")\n",
    "random_generator = pwa.StdUniformRealGenerator(12345)\n",
    "\n",
    "# generate phase space sample\n",
    "phsp_sample = pwa.generate_phsp(int(1e5), generator, random_generator)\n",
    "\n",
    "# create intensity profile\n",
    "intensity_builder = pwa.IntensityBuilderXML(\n",
    "    \"model.xml\", particle_list, kinematics, phsp_sample\n",
    ")\n",
    "intensity = intensity_builder.create_intensity()\n",
    "\n",
    "# generate data\n",
    "data_sample = pwa.generate(\n",
    "    int(1e4), kinematics, generator, intensity, random_generator\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    ":::{note}\n",
    "\n",
    "{mod}`pycompwa.ui` is the python interface to [ComPWA's C++ modules](https://compwa.github.io/ComPWA/annotated.html). It has four major important components for evaluating intensities:\n",
    "  \n",
    "* The {class}`.EventCollection` class is simply an event-based list of four-momenta with a list of Particle IDs.\n",
    "* The {class}`.Kinematics` class allows one to compute kinematic variables, like $(s,\\theta,\\phi)$ in the helicity formalism, from the momentum tuples in an {class}`.EventCollection`.\n",
    "* The {class}`.DataSet` class is the result when you {meth}`~pycompwa.ui.Kinematics.convert` an {class}`.EventCollection`. It is essentially a table of kinematic variables for each event in that original collection of four-momenta.\n",
    "* The {class}`.Intensity` class allows one to compute an intensity (an absolute value) for each data point in the {class}`.DataSet`. You do this computation with the {meth}`~pycompwa.ui.FunctionTreeIntensity.evaluate` method (see {doc}`step4`).\n",
    "\n",
    ":::\n",
    "\n",
    ":::{hint}\n",
    "\n",
    "For more complicated data sample structures, see {ref}`usage/tools/generate:Importance Sampling`.\n",
    "\n",
    ":::"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2.2 Exporting and importing"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The {mod}`pycompwa.ui` module allows you to export the data samples to two different file formats: [ROOT files](https://root.cern/manual/root_files) and ASCII files."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# to ROOT\n",
    "pwa.write_root_data(data_sample, output_file=\"generated_data.root\")\n",
    "pwa.write_root_data(phsp_sample, output_file=\"generated_phsp.root\")\n",
    "# to ASCII\n",
    "pwa.write_ascii_data(data_sample, output_file=\"generated_data.dat\")\n",
    "pwa.write_ascii_data(phsp_sample, output_file=\"generated_phsp.dat\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The syntax for importing parallels that:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "imported_data = pwa.read_root_data(input_file=\"generated_data.root\")\n",
    "imported_phsp = pwa.read_ascii_data(input_file=\"generated_phsp.dat\")\n",
    "\n",
    "print(\"Imported data events:\", len(imported_data.events))\n",
    "print(\"Imported phsp events:\", len(imported_phsp.events))\n",
    "\n",
    "first_event = imported_data.events[0]\n",
    "print(\"First data event:\")\n",
    "print(first_event.four_momenta)\n",
    "print(first_event.weight)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Note that the ASCII (``.dat``) files contain a header section that informs you about the final state of the file. You will have to prepend this section to the file yourself if you want to use an ASCII file that was exported from another framework."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "with open(\"generated_data.dat\") as f:\n",
    "    for _ in range(5):\n",
    "        print(f.readline()[:-1])"
   ]
  }
 ],
 "metadata": {
  "celltoolbar": "Raw Cell Format",
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
