diff --git a/notebooks/2.1_Single-file.ipynb b/notebooks/2.1_Single-file.ipynb index a3b23c4..8789f17 100644 --- a/notebooks/2.1_Single-file.ipynb +++ b/notebooks/2.1_Single-file.ipynb @@ -10,219 +10,160 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "id": "48f3f61b-839b-4ae2-9635-3b81e805ca67", "metadata": {}, "outputs": [], "source": [ "import os, sys\n", "sys.path.append(os.getcwd()+\"/../\")\n", - "from scenarios.generator_2p1 import generate_configs\n", + "import copy\n", + "import yaml\n", + "from src.utils import recreate_dir\n", "from src.benchmark import Benchmark, run_benchmark" ] }, { "cell_type": "code", "execution_count": null, - "id": "b15f6911-00e5-4d23-8c20-f39b5223335d", + "id": "99d4efd9-9672-4590-ac41-a6013b3d8e22", "metadata": {}, "outputs": [], "source": [ - "# warning: all YAML files will be deleted fron this directory before proceeding\n", - "config_path = \"./configs_2.1\"\n", + "default_config = {\n", + " 'data-access': {\n", + " 'mode': 'explicit-files',\n", + " 'files': []\n", + " },\n", + " 'executor': {\n", + " 'backend': 'sequential',\n", + " 'n_workers': 1\n", + " },\n", + " 'processor': {\n", + " 'parallelize_over': 'files',\n", + " 'columns': {},\n", + " 'load_columns_into_memory': True,\n", + " 'worker_operation_time': 0\n", + " }\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "87efdb93-f8c3-4fba-953a-5fa6e2bae407", + "metadata": {}, + "outputs": [], + "source": [ + "file_name = \"90322FC2-4027-0E47-92E4-22307EC8EAD2.root\"\n", + "file_locations = {\n", + " \"depot\": \"/depot/cms/users/dkondra/\",\n", + " # \"work\": \"/work/projects/purdue-af/\",\n", + " # \"eos_fuse\": \"/eos/purdue/store/data/Run2016B/SingleMuon/NANOAOD/02Apr2020_ver2-v1/20000/\",\n", + " # \"xrootd\": \"root://eos.cms.rcac.purdue.edu:1094//store/data/Run2016B/SingleMuon/NANOAOD/02Apr2020_ver2-v1/20000/\",\n", + " # \"xcache\": \"root://cms-xcache.rcac.purdue.edu:1094//store/data/Run2016B/SingleMuon/NANOAOD/02Apr2020_ver2-v1/20000/\"\n", + "}\n", "\n", - "generate_configs(config_path)\n", - "report = run_benchmark(config_path)" + "column_presets = {\n", + " # \"100pct\": {\n", + " # # the bechmark will limit this to actual total number of columns\n", + " # \"method\": \"n_columns\",\n", + " # \"values\": 100000\n", + " # },\n", + " \"50pct\": {\n", + " \"method\": \"collections\",\n", + " \"values\": [\"Jet\", \"Photon\", \"Tau\", \"Electron\", \"Muon\"]\n", + " },\n", + " # \"10pct\": {\n", + " # \"method\": \"collections\",\n", + " # \"values\": [\"Muon\"]\n", + " # },\n", + " # \"5pct\": {\n", + " # \"method\": \"column_list\",\n", + " # \"values\": [\n", + " # \"run\", \"luminosityBlock\", \"HLT_IsoMu24\", \"PV_npvsGood\", \"fixedGridRhoFastjetAll\",\n", + " # \"Muon_pt\", \"Muon_eta\", \"Muon_phi\", \"Muon_mass\", \"Muon_charge\", \"Muon_pfRelIso04_all\", \"Muon_mediumId\", \"Muon_ptErr\",\n", + " # \"Electron_pt\", \"Electron_eta\", \"Electron_mvaFall17V2Iso_WP90\",\n", + " # \"Jet_pt\", \"Jet_eta\", \"Jet_phi\", \"Jet_mass\",\n", + " # ]\n", + " # }\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b437563d-da50-4bda-829b-eeb4218b03f2", + "metadata": {}, + "outputs": [], + "source": [ + "def generate_configs(save_dir=\"./\"):\n", + " recreate_dir(save_dir)\n", + "\n", + " iconf = 0\n", + "\n", + " for f_label, file_loc in file_locations.items():\n", + " for c_label, column_setup in column_presets.items():\n", + " config = copy.deepcopy(default_config)\n", + "\n", + " config[\"data-access\"][\"files\"] = [f\"{file_loc}/{file_name}\"]\n", + " config[\"processor\"][\"columns\"] = column_setup\n", + "\n", + " # Custom labels to save to output dataframe\n", + " config[\"custom_labels\"] = {\n", + " \"file_location\": f_label,\n", + " \"column_setup\": c_label\n", + " }\n", + "\n", + " config_name = f'config2p1_{iconf}_{f_label}_{c_label}.yaml'\n", + " \n", + " with open(f'{save_dir}/{config_name}', 'w') as file:\n", + " yaml.dump(config, file, default_flow_style=False)\n", + "\n", + " iconf += 1\n", + "\n", + " print(f'Saved {iconf} config files to {save_dir}')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "574dea64-da4b-4fba-b610-1dfc734ec077", + "metadata": {}, + "outputs": [], + "source": [ + "# warning: all YAML files will be deleted fron this directory before proceeding\n", + "config_path = \"./configs_2.1\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8633cf12-d9d9-4201-8969-e40868ee2e65", + "metadata": {}, + "outputs": [], + "source": [ + "generate_configs(config_path)" ] }, { "cell_type": "code", - "execution_count": 3, - "id": "8a6570bf-2147-45ee-8bbd-0af5408f2ac2", + "execution_count": null, + "id": "d0ed6b4f-1ce8-4731-87e7-57da3b4abced", "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
n_filesn_columns_readn_eventsloaded_columnsworker_operation_timeexecutorn_workerscompressed_bytesuncompressed_bytesrun_processorruncolumn_setup
0150154321550True0dask-local4265594188112903146718.85490320.201502muons_only
1150154321550True0dask-local2265594188112903146736.06741937.411057muons_only
212061728620True0dask-local41754889125217530908.82883910.453846hmm_columns
31233719138423True0dask-local41152109223563605759181.68931183.107676main_collections
41233719138423True0dask-local211521092235636057591158.832810160.246120main_collections
512061728620True0dask-local217548891252175309016.58997118.113264hmm_columns
\n", - "
" - ], - "text/plain": [ - " n_files n_columns_read n_events loaded_columns worker_operation_time \\\n", - "0 1 50 154321550 True 0 \n", - "1 1 50 154321550 True 0 \n", - "2 1 20 61728620 True 0 \n", - "3 1 233 719138423 True 0 \n", - "4 1 233 719138423 True 0 \n", - "5 1 20 61728620 True 0 \n", - "\n", - " executor n_workers compressed_bytes uncompressed_bytes run_processor \\\n", - "0 dask-local 4 265594188 1129031467 18.854903 \n", - "1 dask-local 2 265594188 1129031467 36.067419 \n", - "2 dask-local 4 175488912 521753090 8.828839 \n", - "3 dask-local 4 1152109223 5636057591 81.689311 \n", - "4 dask-local 2 1152109223 5636057591 158.832810 \n", - "5 dask-local 2 175488912 521753090 16.589971 \n", - "\n", - " run column_setup \n", - "0 20.201502 muons_only \n", - "1 37.411057 muons_only \n", - "2 10.453846 hmm_columns \n", - "3 83.107676 main_collections \n", - "4 160.246120 main_collections \n", - "5 18.113264 hmm_columns " - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ - "report" + "# report = run_benchmark(config_path)\n", + "import cProfile\n", + "cProfile.run('run_benchmark(config_path)', 'profile_output.prof')" ] }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "id": "c0a788da-d160-4c81-95ea-150ef4d9a85e", "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAArMAAAINCAYAAAAtJ/ceAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/H5lhTAAAACXBIWXMAAA9hAAAPYQGoP6dpAABXOklEQVR4nO3dd3QUZcPG4XtTSCGNBEiRAJFO6EUEpEkRlC5SpGOhF1FBwYKKIiqIioDoK1UFFERUkCYEEV6pEaSX0EuoCenJ7nx/+JrPSDGhzU7yu87Zc9jZ2Zl754TkzpNnZmyGYRgCAAAALMjF7AAAAADAzaLMAgAAwLIoswAAALAsyiwAAAAsizILAAAAy6LMAgAAwLIoswAAALAsyiwAAAAsy83sAHeaw+HQqVOn5OvrK5vNZnYcAAAA/INhGLpy5YrCwsLk4pKzsdZcX2ZPnTql8PBws2MAAADgXxw/flxFihTJ0XtyfZn19fWV9OfB8fPzMzkNAAAA/ik+Pl7h4eGZvS0ncn2Z/WtqgZ+fH2UWAADAid3MlFBOAAMAAIBlUWYBAABgWZRZAAAAWFaunzMLAEBeZrfblZ6ebnYM5HGurq5yc3O7I5dJpcwCAJBLJSQk6MSJEzIMw+wogLy9vRUaGqp8+fLd1u1SZgEAyIXsdrtOnDghb29vFSpUiBsHwTSGYSgtLU3nzp1TTEyMSpUqleMbI9wIZRYAgFwoPT1dhmGoUKFC8vLyMjsO8jgvLy+5u7vr6NGjSktLk6en523bNieAAQCQizEiC2dxO0djs2z3jmwVAAAAuAsoswAAALAsyiwAAHAaDRs21LBhw8yOcccVL15ckyZNMjtGrkCZBQAAgGVRZgEAAGBZlFkAAPIAwzCUlJZhyiOnN21wOBwaMWKEAgMDFRISojFjxmS+ZrPZ9Mknn6hly5by9vZWuXLltHHjRh08eFANGzZU/vz5Vbt2bR06dCjzPWPGjFGVKlX0+eefq2jRovLx8VH//v1lt9v1zjvvKCQkRIULF9abb76Z7YyXL1/W008/reDgYHl6eqpChQr64YcfMl9fuHChIiMj5eHhoeLFi2vChAnX3daRI0dks9kUHR2dZfs2m01r166VJK1du1Y2m03Lly9X1apV5eXlpQcffFCxsbFatmyZypUrJz8/P3Xp0kVJSUmZ22nYsKGGDBly3eP51/EpWrSoPDw8FBYWpiFDhmT7ODgDrjMLAEAekJxuV/lXlpuy792vPyTvfNmvHLNmzdLw4cP122+/aePGjerVq5fq1q2rpk2bSpLeeOMNTZw4URMnTtTIkSP1+OOP695779WLL76ookWLqk+fPho0aJCWLVuWuc1Dhw5p2bJl+umnn3To0CF16NBBMTExKl26tKKiorRhwwb16dNHjRs31v3333/DfA6HQy1atNCVK1c0d+5clShRQrt375arq6skaevWrerYsaPGjBmjTp06acOGDRowYICCgoLUq1evnB/AvxkzZowmT54sb29vdezYUR07dpSHh4e+/PJLJSQkqF27dvroo480cuTIbB3Pb775Ru+//77mzZunyMhInTlzRr///vstZbzbKLMAAMCpVKpUSa+++qokqVSpUpo8ebJWr16dWWZ79+6tjh07SpJGjhyp2rVr6+WXX9ZDDz0kSRo6dKh69+6dZZsOh0Off/65fH19Vb58eTVq1Ej79u3T0qVL5eLiojJlymj8+PFau3btv5bZVatWadOmTdqzZ49Kly4tSbr33nszX584caIaN26sl19+WZJUunRp7d69W+++++4tl9mxY8eqbt26kqQnnnhCL774og4dOpS5/w4dOmjNmjVZyuyNjuexY8cUEhKiJk2ayN3dXUWLFtV99913SxnvNsosAAB5gJe7q3a//pBp+86JSpUqZXkeGhqq2NjYa74eHBwsSapYsWKWZSkpKYqPj5efn5+kP68e4Ovrm2UdV1fXLBfyDw4OzrKf64mOjlaRIkUyi+w/7dmzR23atMmyrG7dupo0aZLsdnvmCO7N+Odn9/b2zlKkg4ODtWnTpuu+R8p6PB977DFNmjRJ9957r5o3b66HH35YrVq1kpubdSqidZICAICbZrPZcvSnfjO5u7tneW6z2eRwOK75+l93OLvWsuu95691/m0/1/Nvtwc2DOOqO6/daN7wX4X67+ukp6dfc91/fs7sfIYbrRMeHq59+/Zp5cqVWrVqlQYMGKB3331XUVFRV73PWXECGAAAQA5UqlRJJ06c0P79+6/5evny5bV+/fosyzZs2KDSpUtfc1S2UKFCkqTTp09nLvv7yWB3mpeXl1q3bq0PP/xQa9eu1caNG7Vz5867tv9bZY1f0QAAAJxEgwYNVL9+fT366KOaOHGiSpYsqb1798pms6l5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guHh4WGULVvWmD59utmRTLd8+XJDkrFv3z6zoziF+Ph4Y+jQoUbRokUNT09P49577zVGjx5tpKammh3NNPPnzzfuvfdeI1++fEZISIgxcOBA4/Llyznahs0wDOP2dmwAAADg7siVc2YBAACQN1BmAQAAYFmUWQAAAFgWZRYAAACWRZkFAACAZVFmAQAAYFmUWQAAAFgWZRYAciGbzabFixebHQMA7jjKLADcpHPnzsnd3V1JSUnKyMhQ/vz5dezYMbNjAUCeQpkFgJu0ceNGValSRd7e3tq6dasCAwNVtGhRUzOlpaVZarsAcKsoswBwkzZs2KC6detKktavX5/57+vZuXOnXFxcdP78eUnSpUuX5OLiosceeyxznXHjxql27dqZz6OionTffffJw8NDoaGheuGFF5SRkZH5esOGDTVo0CANHz5cBQsWVNOmTa+579dff13BwcGKjo7OzF6/fn15eXkpPDxcQ4YMUWJiYub6xYsX19ixY9WrVy/5+/vrqaeeUlpamgYNGqTQ0FB5enqqePHiGjduXM4OGgDcZpRZAMiBY8eOKSAgQAEBAZo4caI++eQTBQQEaNSoUVq8eLECAgI0YMCAa763QoUKCgoKUlRUlCRp3bp1CgoK0rp16zLXWbt2rRo0aCBJOnnypB5++GHVrFlTv//+u6ZOnar//Oc/Gjt2bJbtzpo1S25ubvr111/1ySefZHnNMAwNHTpU//nPf7R+/XpVqVJFO3fu1EMPPaT27dtrx44dmj9/vtavX69BgwZlee+7776rChUqaOvWrXr55Zf14YcfasmSJVqwYIH27dunuXPnqnjx4rd6SAHgltgMwzDMDgEAVpGRkaETJ04oPj5eNWrU0ObNm+Xj46MqVaroxx9/VNGiReXj46OCBQte8/2PPvqowsLC9NFHH+mZZ56Rq6urZs2apaioKJUuXVoFChTQ119/rebNm2v06NFauHCh9uzZI5vNJkmaMmWKRo4cqbi4OLm4uKhhw4aKi4vT9u3bs+zHZrPp66+/1nfffactW7Zo5cqVKlKkiCSpR48e8vLyylJ8169frwYNGigxMTFz1LVq1ar69ttvM9cZMmSIdu3apVWrVmXmAQCzMTILADng5uam4sWLa+/evapZs6YqV66sM2fOKDg4WPXr11fx4sWvW2SlP6cFrF27VtKfUwgaNWqk+vXrKyoqSps3b1ZycnLmdIU9e/aodu3aWYpj3bp1lZCQoBMnTmQuq1GjxjX39cwzz2jjxo365ZdfMousJG3dulUzZ86Uj49P5uOhhx6Sw+FQTEzMdbfbq1cvRUdHq0yZMhoyZIhWrFiR/QMHAHeIm9kBAMBKIiMjdfToUaWnp8vhcMjHx0cZGRnKyMiQj4+PihUrpl27dl33/Q0bNtTQoUN18OBB/fHHH6pXr54OHTqkqKgoXb58WdWrV5evr6+kP6cI/HME9K8/pv19ef78+a+5r6ZNm+qrr77S8uXL1bVr18zlDodDffv21ZAhQ656z99PYPvndqtVq6aYmBgtW7ZMq1atUseOHdWkSRN988031/28AHCnUWYBIAeWLl2q9PR0NW7cWO+8846qV6+uzp07q1evXmrevLnc3d1v+P6/5s2OHTtWlStXlp+fnxo0aKBx48bp0qVLmfNlJal8+fJauHBhllK7YcMG+fr66p577vnXrK1bt1arVq30+OOPy9XVVZ07d5b0ZyndtWuXSpYsmePP7+fnp06dOqlTp07q0KGDmjdvrosXLyowMDDH2wKA24FpBgCQA8WKFZOPj4/Onj2rNm3aqGjRotq9e7fat2+vkiVLqlixYjd8v81mU/369TV37lw1bNhQklSpUiWlpaVp9erVmcskacCAATp+/LgGDx6svXv36rvvvtOrr76q4cOHy8Ule9++27Vrpzlz5qh3796ZI6gjR47Uxo0bNXDgQEVHR+vAgQNasmSJBg8efMNtvf/++5o3b5727t2r/fv36+uvv1ZISIgCAgKylQUA7gRGZgEgh9auXauaNWvK09NTv/zyi+655x6FhYVl+/2NGjXSokWLMourzWZTvXr19MMPP+iBBx7IXO+ee+7R0qVL9fzzz6ty5coKDAzUE088oZdeeilHeTt06CCHw6Hu3bvLxcVF7du3V1RUlEaPHq169erJMAyVKFFCnTp1uuF2fHx8NH78eB04cECurq6qWbOmli5dmu1iDQB3AlczAAAAgGXx6zQAAAAsizILAAAAy6LMAgAAwLIoswAAALAsyiwAAAAsizILAAAAy6LMAgAAwLIoswAAALAsyiwAAAAsizILAAAAy6LMAgAAwLIoswAAALCs/wP1VSkdRPZL9QAAAABJRU5ErkJggg==", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "import matplotlib.pyplot as plt\n", "\n", @@ -248,6 +189,40 @@ "id": "3ff7179c-b407-47b6-b8d0-2bb25ed0649b", "metadata": {}, "outputs": [], + "source": [ + "report[\"event_rate\"] = report.n_events / report.run_processor / report.n_columns_read\n", + "report[\"data_rate_comp\"] = report.compressed_bytes / report.run_processor\n", + "report[\"data_rate_uncomp\"] = report.uncompressed_bytes / report.run_processor\n", + "report[[\"column_setup\", \"n_workers\", \"event_rate\", \"data_rate_comp\", \"data_rate_uncomp\"]]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cdc0e36b-a557-407e-98b8-9ca52360933b", + "metadata": {}, + "outputs": [], + "source": [ + "report.compressed_bytes / report.n_events * report.n_columns_read" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "19cd6bd7-6180-4aac-9ab7-6799cf1450dc", + "metadata": {}, + "outputs": [], + "source": [ + "import uproot\n", + "uproot.__version__" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c69265f0-8a41-4014-9ecc-0f9573f173e1", + "metadata": {}, + "outputs": [], "source": [] } ], diff --git a/scenarios/common.py b/scenarios/common.py deleted file mode 100644 index 8476ca8..0000000 --- a/scenarios/common.py +++ /dev/null @@ -1,25 +0,0 @@ - -column_presets = { - # "full_event": { - # # the bechmark will limit this to actual total number of columns - # "method": "n_columns", - # "values": 100000 - # }, - "main_collections": { - "method": "collections", - "values": ["Jet", "Photon", "Tau", "Electron", "Muon"] - }, - "muons_only": { - "method": "collections", - "values": ["Muon"] - }, - "hmm_columns": { - "method": "column_list", - "values": [ - "run", "luminosityBlock", "HLT_IsoMu24", "PV_npvsGood", "fixedGridRhoFastjetAll", - "Muon_pt", "Muon_eta", "Muon_phi", "Muon_mass", "Muon_charge", "Muon_pfRelIso04_all", "Muon_mediumId", "Muon_ptErr", - "Electron_pt", "Electron_eta", "Electron_mvaFall17V2Iso_WP90", - "Jet_pt", "Jet_eta", "Jet_phi", "Jet_mass", - ] - } -} \ No newline at end of file diff --git a/scenarios/generator_2p1.py b/scenarios/generator_2p1.py deleted file mode 100644 index fea5d4f..0000000 --- a/scenarios/generator_2p1.py +++ /dev/null @@ -1,54 +0,0 @@ -import copy -import yaml - -from scenarios.common import column_presets -from scenarios.utils import recreate_dir - - -default_config = { - 'data-access': { - 'mode': 'explicit-files', - 'files': ['/depot/cms/users/dkondra/90322FC2-4027-0E47-92E4-22307EC8EAD2.root'] - }, - 'executor': { - 'backend': 'dask-local', - 'n_workers': 1 - }, - 'processor': { - 'parallelize_over': 'columns', - 'columns': {}, - 'load_columns_into_memory': True, - 'worker_operation_time': 0 - } -} - - -def generate_configs(save_dir="./"): - recreate_dir(save_dir) - - n_workers_opts = [2,4] - # n_workers_opts = [1,2,4,8] - - iconf = 0 - - for n_workers in n_workers_opts: - for label, column_setup in column_presets.items(): - config = copy.deepcopy(default_config) - config["executor"]["n_workers"] = n_workers - config["processor"]["columns"] = column_setup - - # Custom labels to save to output dataframe - config["custom_labels"] = { - "column_setup": label - } - - config_name = f'config2p1_{iconf}_{label}_{n_workers}w.yaml' - - with open(f'{save_dir}/{config_name}', 'w') as file: - yaml.dump(config, file, default_flow_style=False) - - iconf += 1 - - print(f'Saved {iconf} config files to {save_dir}') - - \ No newline at end of file diff --git a/scenarios/utils.py b/scenarios/utils.py deleted file mode 100644 index 874dffc..0000000 --- a/scenarios/utils.py +++ /dev/null @@ -1,12 +0,0 @@ -import os -import glob - -def recreate_dir(save_dir): - if not os.path.exists(save_dir): - os.makedirs(save_dir) - print(f"Directory {save_dir} created.") - else: - print(f"Directory {save_dir} already exists, will clean all YAML files from it.") - yaml_files = glob.glob(f"{save_dir}/*yaml")+glob.glob(f"{save_dir}/*yml") - for file in yaml_files: - os.remove(file) \ No newline at end of file diff --git a/src/uproot_processor.py b/src/uproot_processor.py index f59d8df..5672295 100644 --- a/src/uproot_processor.py +++ b/src/uproot_processor.py @@ -83,15 +83,15 @@ def worker_func(self, args, **kwargs): files = args["files"] columns = args["columns"] for file in files: + tree = self.open_nanoaod(file) for column in columns: - col_stats = self.process_column(file, column, **kwargs) + col_stats = self.process_column(tree, column, **kwargs) col_stats_df = pd.concat([col_stats_df, col_stats]) self.run_worker_operation() return col_stats_df - def process_column(self, file, column, **kwargs): - tree = self.open_nanoaod(file) + def process_column(self, tree, column, **kwargs): column_data = tree[column] col_stats = pd.DataFrame([{ "file": tree.file.file_path,