|  | 
| 50 | 50 |   }, | 
| 51 | 51 |   { | 
| 52 | 52 |    "cell_type": "code", | 
| 53 |  | -   "execution_count": 1, | 
|  | 53 | +   "execution_count": null, | 
| 54 | 54 |    "id": "afa8f0e4-8216-44fd-8770-fbeec0b388cf", | 
| 55 | 55 |    "metadata": {}, | 
| 56 | 56 |    "outputs": [], | 
|  | 
| 600 | 600 |    "id": "14de1930-423b-4c1b-a1cb-d5b0c8d6f6d0", | 
| 601 | 601 |    "metadata": {}, | 
| 602 | 602 |    "source": [ | 
| 603 |  | -    "# Results\n", | 
|  | 603 | +    "# Results" | 
|  | 604 | +   ] | 
|  | 605 | +  }, | 
|  | 606 | +  { | 
|  | 607 | +   "cell_type": "code", | 
|  | 608 | +   "execution_count": null, | 
|  | 609 | +   "id": "53eab109", | 
|  | 610 | +   "metadata": {}, | 
|  | 611 | +   "outputs": [], | 
|  | 612 | +   "source": [ | 
|  | 613 | +    "print(\"JFruit2 sensitivity analysis\")\n", | 
|  | 614 | +    "print(\"=\" * 60)\n", | 
|  | 615 | +    "\n", | 
|  | 616 | +    "# Get results from the calibrator\n", | 
|  | 617 | +    "sp = calibrator.implementation.sp\n", | 
|  | 618 | +    "Y = sp._results\n", | 
|  | 619 | +    "Si = sobol.analyze(sp, Y, calc_second_order=True)\n", | 
|  | 620 | +    "\n", | 
|  | 621 | +    "output_labels = calibrator.specification.output_labels[0]  \n", | 
|  | 622 | +    "\n", | 
|  | 623 | +    "s1_values = Si['S1']\n", | 
|  | 624 | +    "st_values = Si['ST']\n", | 
|  | 625 | +    "parameter_names = sp['names']\n", | 
|  | 626 | +    "\n", | 
|  | 627 | +    "# results summary\n", | 
|  | 628 | +    "sensitivity_df = pd.DataFrame({\n", | 
|  | 629 | +    "    'Parameter': parameter_names,\n", | 
|  | 630 | +    "    'S1 (direct effect)': s1_values,\n", | 
|  | 631 | +    "    'ST (total effect)': st_values,\n", | 
|  | 632 | +    "    'Interactions': st_values - s1_values\n", | 
|  | 633 | +    "}).sort_values('ST (total effect)', ascending=False)\n", | 
|  | 634 | +    "\n", | 
|  | 635 | +    "print(sensitivity_df.to_string(index=False, float_format='%.3f'))\n", | 
|  | 636 | +    "\n", | 
|  | 637 | +    "print(\"=\" * 60)\n", | 
|  | 638 | +    "for _, row in sensitivity_df.iterrows():\n", | 
|  | 639 | +    "    param = row['Parameter']\n", | 
|  | 640 | +    "    s1 = row['S1 (direct effect)']\n", | 
|  | 641 | +    "    st = row['ST (total effect)']\n", | 
|  | 642 | +    "    \n", | 
|  | 643 | +    "    print(f\"\\n• {param}: {st:.1%} total influence on {output_labels}\")\n", | 
|  | 644 | +    "    \n", | 
|  | 645 | +    "    if 'Growth.lp' in param:\n", | 
|  | 646 | +    "        print(f\"  - Controls how quickly the fruit grows\")\n", | 
|  | 647 | +    "    elif 'Growth.lxAsy' in param:\n", | 
|  | 648 | +    "        print(f\"  - Sets the maximum potential fruit size\")\n", | 
|  | 649 | +    "    \n", | 
|  | 650 | +    "    if st > 0.1:\n", | 
|  | 651 | +    "        print(f\"  - 🔴 HIGH importance - prioritize for calibration\")\n", | 
|  | 652 | +    "    elif st > 0.05:\n", | 
|  | 653 | +    "        print(f\"  - 🟡 MEDIUM importance - secondary calibration target\")\n", | 
|  | 654 | +    "    else:\n", | 
|  | 655 | +    "        print(f\"  - 🟢 LOW importance - can use literature values\")\n", | 
|  | 656 | +    "\n", | 
|  | 657 | +    "\n", | 
|  | 658 | +    "print(\"=\" * 60)\n", | 
|  | 659 | +    "most_important = sensitivity_df.iloc[0]\n", | 
|  | 660 | +    "max_interaction = sensitivity_df['Interactions'].max()\n", | 
|  | 661 | +    "\n", | 
|  | 662 | +    "print(f\"• Most important parameter: {most_important['Parameter']} ({most_important['ST (total effect)']:.1%} influence)\")\n", | 
|  | 663 | +    "print(f\"• Parameter interactions: {'Strong' if max_interaction > 0.1 else 'Weak'}\")\n", | 
|  | 664 | +    "\n", | 
|  | 665 | +    "if max_interaction > 0.1:\n", | 
|  | 666 | +    "    print(f\"  → Calibrate parameters together, not separately\")\n", | 
|  | 667 | +    "else:\n", | 
|  | 668 | +    "    print(f\"  → Parameters can be calibrated independently\")\n", | 
| 604 | 669 |     "\n", | 
| 605 |  | -    "According to the plots above..." | 
|  | 670 | +    "total_explained = np.sum(st_values)\n", | 
|  | 671 | +    "print(f\"• Model variance explained: {total_explained:.1%}\")\n", | 
|  | 672 | +    "if total_explained > 0.8:\n", | 
|  | 673 | +    "    print(f\"  → The parameters explain most model behaviours in the response variables\")\n", | 
|  | 674 | +    "else:\n", | 
|  | 675 | +    "    print(f\"  → The model outputs are not sensitive to the parameter set selected\")" | 
| 606 | 676 |    ] | 
| 607 | 677 |   } | 
| 608 | 678 |  ], | 
| 609 | 679 |  "metadata": { | 
| 610 | 680 |   "kernelspec": { | 
| 611 |  | -   "display_name": "Python 3 (ipykernel)", | 
|  | 681 | +   "display_name": "Python 3", | 
| 612 | 682 |    "language": "python", | 
| 613 | 683 |    "name": "python3" | 
| 614 | 684 |   }, | 
|  | 
| 622 | 692 |    "name": "python", | 
| 623 | 693 |    "nbconvert_exporter": "python", | 
| 624 | 694 |    "pygments_lexer": "ipython3", | 
| 625 |  | -   "version": "3.10.17" | 
|  | 695 | +   "version": "3.10.5" | 
| 626 | 696 |   } | 
| 627 | 697 |  }, | 
| 628 | 698 |  "nbformat": 4, | 
|  | 
0 commit comments