|
4 | 4 | import logging |
5 | 5 | import os |
6 | 6 | import tempfile |
| 7 | +from collections.abc import Sequence |
7 | 8 | from math import nan |
| 9 | +from numbers import Number |
8 | 10 | from pathlib import Path |
9 | 11 | from typing import TYPE_CHECKING |
10 | 12 |
|
@@ -724,3 +726,133 @@ def validate( |
724 | 726 | break |
725 | 727 |
|
726 | 728 | return validation_results |
| 729 | + |
| 730 | + def add_condition(self, id_: str, name: str = None, **kwargs): |
| 731 | + """Add a simulation condition to the problem. |
| 732 | +
|
| 733 | + Arguments: |
| 734 | + id_: The condition id |
| 735 | + name: The condition name |
| 736 | + kwargs: Parameter, value pairs to add to the condition table. |
| 737 | + """ |
| 738 | + record = {CONDITION_ID: [id_], **kwargs} |
| 739 | + if name is not None: |
| 740 | + record[CONDITION_NAME] = name |
| 741 | + tmp_df = pd.DataFrame(record).set_index([CONDITION_ID]) |
| 742 | + if self.condition_df is None: |
| 743 | + self.condition_df = tmp_df |
| 744 | + else: |
| 745 | + self.condition_df = pd.concat([self.condition_df, tmp_df]) |
| 746 | + |
| 747 | + def add_observable( |
| 748 | + self, |
| 749 | + id_: str, |
| 750 | + formula: str, |
| 751 | + noise_formula: str | float | int = None, |
| 752 | + noise_distribution: str = None, |
| 753 | + transform: str = None, |
| 754 | + name: str = None, |
| 755 | + **kwargs, |
| 756 | + ): |
| 757 | + """Add an observable to the problem. |
| 758 | +
|
| 759 | + Arguments: |
| 760 | + id_: The observable id |
| 761 | + formula: The observable formula |
| 762 | + noise_formula: The noise formula |
| 763 | + noise_distribution: The noise distribution |
| 764 | + transform: The observable transformation |
| 765 | + name: The observable name |
| 766 | + kwargs: additional columns/values to add to the observable table |
| 767 | +
|
| 768 | + """ |
| 769 | + record = { |
| 770 | + OBSERVABLE_ID: [id_], |
| 771 | + OBSERVABLE_FORMULA: [formula], |
| 772 | + } |
| 773 | + if name is not None: |
| 774 | + record[OBSERVABLE_NAME] = [name] |
| 775 | + if noise_formula is not None: |
| 776 | + record[NOISE_FORMULA] = [noise_formula] |
| 777 | + if noise_distribution is not None: |
| 778 | + record[NOISE_DISTRIBUTION] = [noise_distribution] |
| 779 | + if transform is not None: |
| 780 | + record[OBSERVABLE_TRANSFORMATION] = [transform] |
| 781 | + record.update(kwargs) |
| 782 | + |
| 783 | + tmp_df = pd.DataFrame(record).set_index([OBSERVABLE_ID]) |
| 784 | + if self.observable_df is None: |
| 785 | + self.observable_df = tmp_df |
| 786 | + else: |
| 787 | + self.observable_df = pd.concat([self.observable_df, tmp_df]) |
| 788 | + |
| 789 | + def add_parameter( |
| 790 | + self, |
| 791 | + id_: str, |
| 792 | + estimated: bool | str | int = True, |
| 793 | + nominal_value=None, |
| 794 | + scale: str = None, |
| 795 | + lb: Number = None, |
| 796 | + ub: Number = None, |
| 797 | + init_prior_type: str = None, |
| 798 | + init_prior_pars: str | Sequence = None, |
| 799 | + obj_prior_type: str = None, |
| 800 | + obj_prior_pars: str | Sequence = None, |
| 801 | + **kwargs, |
| 802 | + ): |
| 803 | + """Add a parameter to the problem. |
| 804 | +
|
| 805 | + Arguments: |
| 806 | + id_: The parameter id |
| 807 | + estimated: Whether the parameter is estimated |
| 808 | + nominal_value: The nominal value of the parameter |
| 809 | + scale: The parameter scale |
| 810 | + lb: The lower bound of the parameter |
| 811 | + ub: The upper bound of the parameter |
| 812 | + init_prior_type: The type of the initialization prior distribution |
| 813 | + init_prior_pars: The parameters of the initialization prior |
| 814 | + distribution |
| 815 | + obj_prior_type: The type of the objective prior distribution |
| 816 | + obj_prior_pars: The parameters of the objective prior distribution |
| 817 | + kwargs: additional columns/values to add to the parameter table |
| 818 | + """ |
| 819 | + record = { |
| 820 | + PARAMETER_ID: [id_], |
| 821 | + } |
| 822 | + if estimated is not None: |
| 823 | + record[ESTIMATE] = [ |
| 824 | + int(estimated) |
| 825 | + if isinstance(estimated, bool | int) |
| 826 | + else estimated |
| 827 | + ] |
| 828 | + if nominal_value is not None: |
| 829 | + record[NOMINAL_VALUE] = [nominal_value] |
| 830 | + if scale is not None: |
| 831 | + record[PARAMETER_SCALE] = [scale] |
| 832 | + if lb is not None: |
| 833 | + record[LOWER_BOUND] = [lb] |
| 834 | + if ub is not None: |
| 835 | + record[UPPER_BOUND] = [ub] |
| 836 | + if init_prior_type is not None: |
| 837 | + record[INITIALIZATION_PRIOR_TYPE] = [init_prior_type] |
| 838 | + if init_prior_pars is not None: |
| 839 | + if not isinstance(init_prior_pars, str): |
| 840 | + init_prior_pars = PARAMETER_SEPARATOR.join( |
| 841 | + map(str, init_prior_pars) |
| 842 | + ) |
| 843 | + record[INITIALIZATION_PRIOR_PARAMETERS] = [init_prior_pars] |
| 844 | + if obj_prior_type is not None: |
| 845 | + record[OBJECTIVE_PRIOR_TYPE] = [obj_prior_type] |
| 846 | + if obj_prior_pars is not None: |
| 847 | + if not isinstance(obj_prior_pars, str): |
| 848 | + obj_prior_pars = PARAMETER_SEPARATOR.join( |
| 849 | + map(str, obj_prior_pars) |
| 850 | + ) |
| 851 | + record[OBJECTIVE_PRIOR_PARAMETERS] = [obj_prior_pars] |
| 852 | + record.update(kwargs) |
| 853 | + |
| 854 | + tmp_df = pd.DataFrame(record).set_index([PARAMETER_ID]) |
| 855 | + if self.parameter_df is None: |
| 856 | + self.parameter_df = tmp_df |
| 857 | + else: |
| 858 | + self.parameter_df = pd.concat([self.parameter_df, tmp_df]) |
0 commit comments