{ "nbformat": 4, "nbformat_minor": 0, "metadata": { "colab": { "provenance": [], "authorship_tag": "ABX9TyN7KrJ5aFUDzz8ZbDcCHGEo", "include_colab_link": true }, "kernelspec": { "name": "python3", "display_name": "Python 3" }, "language_info": { "name": "python" } }, "cells": [ { "cell_type": "markdown", "metadata": { "id": "view-in-github", "colab_type": "text" }, "source": [ "" ] }, { "cell_type": "markdown", "source": [ "# Intro\n", "\n", "This notebook demonstrates an example of how to use [the Primavera P6 xer files reader](https://pypi.org/project/xerparser/0.10.3/) library for data preparation.\n", "\n", "\n", "The XER file contains the same data presented in the [notebook](https://nbviewer.org/github/inigmat/exupery/blob/main/Schedule_CPLEX.ipynb) which is shown in the [\"Optimizing Project Planning and Material transportation\"](https://inigmat.github.io/home/2023/11/29/Transport-and-Resources.html) post.\n", "\n", "By obtaining the file via URL link, the required data—task names, durations, precedences, and release dates (intervals between each house's earliest starting date)—is transformed into Python objects.\n" ], "metadata": { "id": "BhG4x-GqoR_3" } }, { "cell_type": "markdown", "source": [ "# Installing xerparser\n" ], "metadata": { "id": "EYEH5p-0oF4Z" } }, { "cell_type": "code", "source": [ "import importlib\n", "\n", "# Check if xerparser is already installed\n", "try:\n", " importlib.import_module('xerparser')\n", " print(\"xerparser is already installed.\")\n", "except ImportError:\n", " try:\n", " # Attempt installation\n", " %pip install xerparser\n", " except Exception as e:\n", " print(\"An error occurred while installing xerparser:\", e)" ], "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "gbiCgG_RUiY0", "outputId": "bb1d4cc0-73ad-410f-ee4c-0fe89d11d7a2" }, "execution_count": null, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "xerparser is already installed.\n" ] } ] }, { "cell_type": "markdown", "source": [ "# Getting the XER file" ], "metadata": { "id": "sya1fu_QqTgW" } }, { "cell_type": "code", "source": [ "import requests\n", "\n", "url = \"https://raw.githubusercontent.com/inigmat/exupery/main/files/schedule/MDL4D.xer\"\n", "\n", "try:\n", " response = requests.get(url)\n", " if response.status_code == 200:\n", " print(\"Request successful!\")\n", " else:\n", " print(f\"Failed to retrieve data. Status code: {response.status_code}\")\n", "except requests.exceptions.RequestException as e:\n", " print(f\"An error occurred: {e}\")" ], "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "sjlr83pETrsi", "outputId": "9559e561-2f45-496c-9ab3-a0276502c925" }, "execution_count": null, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "Request successful!\n" ] } ] }, { "cell_type": "markdown", "source": [ "# Read the downloaded file with checking for errors" ], "metadata": { "id": "9nLeMn863_fl" } }, { "cell_type": "code", "source": [ "from xerparser import Xer, CorruptXerFile\n", "\n", "try:\n", " xer = Xer(response.text)\n", "except CorruptXerFile as e:\n", " for error in e.errors:\n", " print(error)" ], "metadata": { "id": "-G_0Dr4lJhul" }, "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "source": [ "# Getting the project data" ], "metadata": { "id": "2qKhVOAF37Yl" } }, { "cell_type": "code", "source": [ "project = list(xer.projects.values())[0]" ], "metadata": { "id": "q1zW1dI7fxJT" }, "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "source": [ "We have to get the following data\n", "\n", "```\n", "NbWorkers = 3\n", "NbHouses = 5\n", "\n", "TaskNames = (\"masonry\",\"carpentry\",\"plumbing\",\n", " \"ceiling\",\"roofing\",\"painting\",\n", " \"windows\",\"facade\",\"garden\",\"moving\")\n", "\n", "Duration = [35, 15, 40, 15, 5, 10, 5, 10, 5, 5]\n", "\n", "ReleaseDate = [31, 0, 90, 120, 90]\n", "\n", "Precedences = [(\"masonry\", \"carpentry\"), (\"masonry\", \"plumbing\"), (\"masonry\", \"ceiling\"),\n", " (\"carpentry\", \"roofing\"), (\"ceiling\", \"painting\"), (\"roofing\", \"windows\"),\n", " (\"roofing\", \"facade\"), (\"plumbing\", \"facade\"), (\"roofing\", \"garden\"),\n", " (\"plumbing\", \"garden\"), (\"windows\", \"moving\"), (\"facade\", \"moving\"),\n", " (\"garden\", \"moving\"), (\"painting\", \"moving\")]\n", "```\n", "\n" ], "metadata": { "id": "WwED080mhUzT" } }, { "cell_type": "markdown", "source": [ "# Start with getting the WBS (house numbers)\n", "\n", "We skip the first two levels using WBS_LVL variable" ], "metadata": { "id": "9ECY5LtO4l-F" } }, { "cell_type": "code", "source": [ "WBS_LVL = 2\n", "houses = [obj.name for obj in project.wbs_nodes[WBS_LVL:]]\n", "NbHouses= len(houses)\n", "houses" ], "metadata": { "id": "h_slxPqjRvWH", "colab": { "base_uri": "https://localhost:8080/" }, "outputId": "2db66196-9c1f-4646-e4e4-a9f8791ea424" }, "execution_count": null, "outputs": [ { "output_type": "execute_result", "data": { "text/plain": [ "['House 1', 'House 2', 'House 3', 'House 4', 'House 5']" ] }, "metadata": {}, "execution_count": 5 } ] }, { "cell_type": "markdown", "source": [ "# Obtain the labor resources of the project to get the number of workers" ], "metadata": { "id": "mnuxHbRR5mqB" } }, { "cell_type": "code", "source": [ "workers = {}\n", "for res in project.resources:\n", " if res.rsrc_type == \"RT_Labor\":\n", " workers[res.rsrc_id] = res.resource.name\n", "NbWorkers = len(workers)" ], "metadata": { "id": "spxHZUTpareG" }, "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "source": [ "# Prepare pandas dataframe to check out the tasks data such as 'TASK ID','Name','Type', 'WBS ID', 'Duration', 'Successors (ID, Link, Lag)'" ], "metadata": { "id": "RFsILb_753_3" } }, { "cell_type": "code", "source": [ "import pandas as pd\n", "\n", "tasks_df = pd.DataFrame(columns=['TASK ID','Name','Type', 'WBS ID', 'Duration', 'Successors (ID, Link, Lag)'])\n", "\n", "for task in project.tasks:\n", " task_sucs = []\n", " for pred_link in task.successors:\n", " task_suc = pred_link.task.uid\n", " task_link = pred_link.link\n", " task_lag = pred_link.lag\n", " task_sucs.append((task_suc, task_link, task_lag))\n", "\n", " tasks_df = pd.concat([tasks_df, pd.DataFrame(\n", " {'TASK ID': [task.uid],\n", " 'Name': [task.name],\n", " 'Type': [task.type],\n", " 'WBS ID': [task.wbs_id],\n", " 'Duration': [task.duration],\n", " 'Successors (ID, Link, Lag)': [task_sucs],\n", " })], ignore_index=True)" ], "metadata": { "id": "SdzXOiYMmBiK" }, "execution_count": null, "outputs": [] }, { "cell_type": "code", "source": [ "tasks_df.head(15)" ], "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 514 }, "id": "dAkhLXxm5ph6", "outputId": "36199cdb-a44e-4d67-d913-35478941617c" }, "execution_count": null, "outputs": [ { "output_type": "execute_result", "data": { "text/plain": [ " TASK ID Name Type WBS ID Duration \\\n", "0 104836 House 1 Start TaskType.TT_Mile 26152 0 \n", "1 104837 Masonry TaskType.TT_Task 26154 35 \n", "2 104838 Carpentry TaskType.TT_Task 26154 15 \n", "3 104839 Plumbing TaskType.TT_Task 26154 40 \n", "4 104840 Ceiling TaskType.TT_Task 26154 15 \n", "5 104841 Roofing TaskType.TT_Task 26154 5 \n", "6 104842 Painting TaskType.TT_Task 26154 10 \n", "7 104843 Windows TaskType.TT_Task 26154 5 \n", "8 104844 Facade TaskType.TT_Task 26154 10 \n", "9 104845 Garden TaskType.TT_Task 26154 5 \n", "10 104846 Moving TaskType.TT_Rsrc 26154 5 \n", "11 104847 House 2 Start TaskType.TT_Mile 26152 0 \n", "12 104848 Masonry TaskType.TT_Task 26155 35 \n", "13 104849 Carpentry TaskType.TT_Task 26155 15 \n", "14 104850 Plumbing TaskType.TT_Task 26155 40 \n", "\n", " Successors (ID, Link, Lag) \n", "0 [] \n", "1 [(104838, FS, 0), (104839, FS, 0), (104840, FS... \n", "2 [(104841, FS, 0)] \n", "3 [(104844, FS, 0), (104845, FS, 0)] \n", "4 [(104842, FS, 0)] \n", "5 [(104843, FS, 0), (104844, FS, 0), (104845, FS... \n", "6 [(104846, FS, 0)] \n", "7 [(104846, FS, 0)] \n", "8 [(104846, FS, 0)] \n", "9 [(104846, FS, 0)] \n", "10 [(104883, FF, 0)] \n", "11 [] \n", "12 [(104849, FS, 0), (104850, FS, 0), (104851, FS... \n", "13 [(104852, FS, 0)] \n", "14 [(104855, FS, 0), (104856, FS, 0)] " ], "text/html": [ "\n", "
\n", " | TASK ID | \n", "Name | \n", "Type | \n", "WBS ID | \n", "Duration | \n", "Successors (ID, Link, Lag) | \n", "
---|---|---|---|---|---|---|
0 | \n", "104836 | \n", "House 1 Start | \n", "TaskType.TT_Mile | \n", "26152 | \n", "0 | \n", "[] | \n", "
1 | \n", "104837 | \n", "Masonry | \n", "TaskType.TT_Task | \n", "26154 | \n", "35 | \n", "[(104838, FS, 0), (104839, FS, 0), (104840, FS... | \n", "
2 | \n", "104838 | \n", "Carpentry | \n", "TaskType.TT_Task | \n", "26154 | \n", "15 | \n", "[(104841, FS, 0)] | \n", "
3 | \n", "104839 | \n", "Plumbing | \n", "TaskType.TT_Task | \n", "26154 | \n", "40 | \n", "[(104844, FS, 0), (104845, FS, 0)] | \n", "
4 | \n", "104840 | \n", "Ceiling | \n", "TaskType.TT_Task | \n", "26154 | \n", "15 | \n", "[(104842, FS, 0)] | \n", "
5 | \n", "104841 | \n", "Roofing | \n", "TaskType.TT_Task | \n", "26154 | \n", "5 | \n", "[(104843, FS, 0), (104844, FS, 0), (104845, FS... | \n", "
6 | \n", "104842 | \n", "Painting | \n", "TaskType.TT_Task | \n", "26154 | \n", "10 | \n", "[(104846, FS, 0)] | \n", "
7 | \n", "104843 | \n", "Windows | \n", "TaskType.TT_Task | \n", "26154 | \n", "5 | \n", "[(104846, FS, 0)] | \n", "
8 | \n", "104844 | \n", "Facade | \n", "TaskType.TT_Task | \n", "26154 | \n", "10 | \n", "[(104846, FS, 0)] | \n", "
9 | \n", "104845 | \n", "Garden | \n", "TaskType.TT_Task | \n", "26154 | \n", "5 | \n", "[(104846, FS, 0)] | \n", "
10 | \n", "104846 | \n", "Moving | \n", "TaskType.TT_Rsrc | \n", "26154 | \n", "5 | \n", "[(104883, FF, 0)] | \n", "
11 | \n", "104847 | \n", "House 2 Start | \n", "TaskType.TT_Mile | \n", "26152 | \n", "0 | \n", "[] | \n", "
12 | \n", "104848 | \n", "Masonry | \n", "TaskType.TT_Task | \n", "26155 | \n", "35 | \n", "[(104849, FS, 0), (104850, FS, 0), (104851, FS... | \n", "
13 | \n", "104849 | \n", "Carpentry | \n", "TaskType.TT_Task | \n", "26155 | \n", "15 | \n", "[(104852, FS, 0)] | \n", "
14 | \n", "104850 | \n", "Plumbing | \n", "TaskType.TT_Task | \n", "26155 | \n", "40 | \n", "[(104855, FS, 0), (104856, FS, 0)] | \n", "