{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Building Blocks of a Timbre Simulation\n", "\n", "The example below represents a situation where one has a 21500 second hot dwell at 90.2 degrees pitch that they want to\n", "include in a schedule near January 1st, 2021. They want to know how much time at 148.95 degrees pitch that should be\n", "included in the schedule to balance this hot dwell from an ACA perspective.\n", "\n", "\n", "## Package Imports" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "from cxotime import CxoTime\n", "from timbre import get_local_model, find_second_dwell" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Define Model Information\n", "\n", "This information defines the model being used, as well as initial starting conditions. These starting conditions do not significantly impact the results, however it is good practice to set them to be close to realistic values." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "msid = \"aacccdpt\"\n", "limit = -6.5\n", "date = \"2021:001:00:00:00\"\n", "aca_model_spec, aca_md5 = get_local_model(\"../timbre/tests/data/aca_spec.json\")\n", "model_init = {\"aacccdpt\": -6.5, \"aca0\": -6.5, \"eclipse\": False}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Define Dwell #1 Information\n", "\n", "Define the state information for the observation that one wants to balance, such as a known hot dwell to be\n", "included in a schedule. For the ACA model, we only need to define dwell time and pitch. Other models may need to have\n", "more information defined. For example, the DPA model would need FEP count, CCD count, SIM position, clocking state, and\n", "vid board state defined. Any information that the Xija model needs to run, that isn't defined in `model_init` needs to\n", "be defined in each of the dwell state definitions, `dwell1_state` and `dwell2_state`." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "t_dwell1 = 21500.0 # Seconds\n", "dwell1_state = {\"pitch\": 90.2}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Define Dwell #2 Information\n", "\n", "This state can be considered a candidate balancing dwell, such as a cooling attitude one wants to use to balance a hot\n", "attitude. In this case we want to calculate the cold time necessary to balance the hot dwell 1 state, so we do not\n", "define time as in input parameter. As with `dwell1_state`, `dwell2_state` still needs all information, not already in\n", "the initialization object `model_init`, necessary to run the Xija model." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "dwell2_state = {\"pitch\": 148.95}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Calculate Dwell #2 Time" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "results = find_second_dwell(\n", " date,\n", " dwell1_state,\n", " dwell2_state,\n", " t_dwell1,\n", " msid,\n", " limit,\n", " aca_model_spec,\n", " model_init,\n", " limit_type=\"max\",\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Explanation of Results\n", "\n", "The following information is returned by `find_second_dwell`:\n", "\n", " - `converged`: This is a boolean value that indicates whether or not a solution was possible. Solutions will not be\n", " possible in a number of situations:\n", "\n", " + Both dwells heat the location being modeled.\n", " + Both dwells cool the location being modeled.\n", " + One of the states neither sufficiently heats or cools the location being modeled (this will sometimes converge but\n", " not always reliably).\n", " + The `dwell1_state` is hot and the initial dwell time is long enough to heat this location from a steady state cold\n", " temperature to the specified hot limit, assuming the location is associated with a maximum temperature limit. In\n", " the case where a location is associated with a minimum temperature limit (e.g. PLINE03T), the opposite would apply,\n", " the `dwell1_state` is cold and is long enough to cool this location from a steady state hot temperature to the\n", " specified cold limit.\n", "\n", " - `unconverged_hot`: If the solution didn't converge, this will be `True` if the input values resulted in temperatures\n", " outside (e.g. above) the specified limit.\n", " - `unconverged_cold`: If the solution didn't converge, this will be `True` if the input values resulted in all\n", " temperatures within (e.g. below) the specified limit.\n", " - `min_temp`: This is the minimum temperature observed during the simulation (latter 2/3 actually to allow the model to\n", " reach a repeatable pattern - more on this later). This will be the limit for a converged solution in the case where\n", " the location is associated with a minimum temperature limit (e.g. PLINE03T).\n", " - `mean_temp`: This is the mean temperature observed during the simulation (latter 2/3)\n", " - `max_temp`: This is the maximum temperature observed during the simulation (latter 2/3). This will be the limit for a\n", " converged solution with a maximum temperature limit (e.g. AACCCDPT).\n", " - `temperature_limit`: This is the limit being used.\n", " - **`dwell2_time`: The dwell #2 time is what you are looking to calculate, and represents the dwell #2 state duration\n", " that balances the dwell #1 state at the specified duration, `t_dwell1`.**\n", " - `min_pseudo`: This is the min pseudo node temperature observed during the evaluated portion of the simulation. This\n", " is not implemented yet but is intended to eventually yield additional insight into the results.\n", " - `mean_pseudo`: This is the mean pseudo node temperature observed during the evaluated portion of the simulation. This\n", " is not implemented yet.\n", " - `max_pseudo`: This is the max pseudo node temperature observed during the evaluated portion of the simulation. This\n", " is not implemented yet.\n", " - `hotter_state`: This is an integer indicating which state is hotter, 1 or 2.\n", " - `colder_state`: This is an integer indicating which state is colder, 1 or 2, and is actually redundant with\n", " `hotter_state`.\n" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'converged': True,\n", " 'unconverged_hot': False,\n", " 'unconverged_cold': False,\n", " 'min_temp': -7.156585351574264,\n", " 'mean_temp': -6.791883371289597,\n", " 'max_temp': -6.5,\n", " 'temperature_limit': -6.5,\n", " 'dwell_2_time': 47284.94444514031,\n", " 'min_pseudo': nan,\n", " 'mean_pseudo': nan,\n", " 'max_pseudo': nan,\n", " 'hotter_state': 1,\n", " 'colder_state': 2}" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "results" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Batch Processing\n", "\n", "Multiple sets of cases can be run using a single function call, simplifying the generation of larger datasets." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Package Imports\n", "\n", "The only difference from above is the import of `run_state_pairs` and `numpy`." ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "from cxotime import CxoTime\n", "from timbre import get_local_model, run_state_pairs" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Define Model Information\n", "\n", "This is the same setup as used above." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "msid = \"aacccdpt\"\n", "limit = -6.5\n", "date = \"2021:001:00:00:00\"\n", "aca_model_spec, aca_md5 = get_local_model(\"../timbre/tests/data/aca_spec.json\")\n", "model_init = {\"aacccdpt\": -6.5, \"aca0\": -6.5, \"eclipse\": False}\n", "t_dwell1 = 21500.0 # Seconds" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Define Dwell Cases\n", "\n", "This is the most significant departure from above, instead of defining separate `dwell1_state` and `dwell2_state` dictionary objects for a single case, pairs of `dwell1_state` and `dwell2_state` dictionary objects are combined into a larger data structure. The `run_state_pairs` function will run through this data structure one pair at a time.\n", "\n", "It should be noted that this set of cases will all use the same initial dwell time `t_dwell1` listed above.\n", "\n", "If one wishes the the return datatype for pitch to be a float, floats should be passed as inputs for all parameters of a given parameter (e.g. pitch)." ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "state_pairs = (\n", " ({\"pitch\": 144.2}, {\"pitch\": 154.95}),\n", " ({\"pitch\": 90.2}, {\"pitch\": 148.95}),\n", " ({\"pitch\": 50.0}, {\"pitch\": 140.0}),\n", " ({\"pitch\": 90.0}, {\"pitch\": 100.0}),\n", " ({\"pitch\": 75.0}, {\"pitch\": 130.0}),\n", " ({\"pitch\": 170.0}, {\"pitch\": 90.0}),\n", " ({\"pitch\": 90.0}, {\"pitch\": 170.0}),\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Calculate Results" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Running simulations for state pair #: 1 out of 7.0\n" ] } ], "source": [ "results = run_state_pairs(\n", " msid,\n", " aca_model_spec,\n", " model_init,\n", " limit,\n", " date,\n", " t_dwell1,\n", " state_pairs,\n", " limit_type=\"max\",\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Explanation of Results Format\n", "\n", "The description of the results shown above is still valid for the similarly named items, however that information is\n", "still included here for completeness, along with descriptions of the additional included information.\n", "\n", " - `msid`: This is the MSID that represents the location of interest, and is the primary output of a given model.\n", " - `date`: This is the date for which the simulation is applicable.\n", " - `datesecs`: This is the same date described by `date` only in seconds using the standard Ska Chandra epoch\n", " - `limit`: This is the temperature limit being used.\n", " - `tdwell_1`: This is the initial, \"known\", time that corresponds to the dwell #1 state. This is fixed for a batch of\n", " `state_pairs`.\n", " - **`tdwell_2`: The dwell #2 time is what you are looking to calculate, and represents the dwell #2 state duration that\n", " balances the dwell #1 state at the specified duration, `t_dwell1`.**\n", " - `min_temp`: This is the minimum temperature observed during the simulation (latter 2/3 actually to allow the model to\n", " reach a repeatable pattern - more on this later). This will be the limit for a converged solution in the case where\n", " the location is associated with a minimum temperature limit (e.g. PLINE03T).\n", " - `mean_temp`: This is the mean temperature observed during the simulation (latter 2/3)\n", " - `max_temp`: This is the maximum temperature observed during the simulation (latter 2/3). This will be the limit for a\n", " converged solution with a maximum temperature limit (e.g. AACCCDPT).\n", " - `min_pseudo`: This is the min pseudo node temperature observed during the evaluated portion of the simulation. This\n", " is not implemented yet but is intended to eventually yield additional insight into the results.\n", " - `mean_pseudo`: This is the mean pseudo node temperature observed during the evaluated portion of the simulation. This\n", " is not implemented yet.\n", " - `max_pseudo`: This is the max pseudo node temperature observed during the evaluated portion of the simulation. This\n", " is not implemented yet.\n", " - `converged`: This is a boolean value that indicates whether or not a solution was possible. Solutions will not be\n", " possible in a number of situations:\n", "\n", " - Both dwells heat the location being modeled.\n", " - Both dwells cool the location being modeled.\n", " - One of the states neither sufficiently heats or cools the location being modeled (this will sometimes converge but\n", " not always reliably).\n", " - The `dwell1_state` is hot and the initial dwell time is long enough to heat this location from a steady state cold\n", " temperature to the specified hot limit, assuming the location is associated with a maximum temperature limit. In\n", " the case where a location is associated with a minimum temperature limit (e.g. PLINE03T), the opposite would apply,\n", " the `dwell1_state` is cold and is long enough to cool this location from a steady state hot temperature to the\n", " specified cold limit.\n", "\n", " - `unconverged_hot`: If the solution didn't converge, this will be `True` if the input values resulted in temperatures\n", " outside (e.g. above) the specified limit.\n", " - `unconverged_cold`: If the solution didn't converge, this will be `True` if the input values resulted in all\n", " temperatures within (e.g. below) the specified limit.\n", " - `hotter_state`: This is an integer indicating which state is hotter, 1 or 2.\n", " - `colder_state`: This is an integer indicating which state is colder, 1 or 2, and is actually redundant with\n", " `hotter_state`.\n", " - `pitch1`: This is the pitch used as an input to a given simulation corresponding to the dwell #1 state.\n", " - `eclipse1`: This is the eclipse state used as an input to a given simulation corresponding to the dwell #1 state.\n", " - `pitch2`: This is the pitch used as an input to a given simulation corresponding to the dwell #2 state.\n", " - `eclipse2`: This is the eclipse state used as an input to a given simulation corresponding to the dwell #2 state." ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "scrolled": false }, "outputs": [ { "data": { "text/html": [ "Table length=7\n", "
| msid | date | datesecs | limit | t_dwell1 | t_dwell2 | min_temp | mean_temp | max_temp | min_pseudo | mean_pseudo | max_pseudo | converged | unconverged_hot | unconverged_cold | hotter_state | colder_state | pitch1 | eclipse1 | pitch2 | eclipse2 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| str20 | str8 | float64 | float64 | float64 | float64 | float64 | float64 | float64 | float64 | float64 | float64 | bool | bool | bool | int8 | int8 | float64 | bool | float64 | bool |
| aacccdpt | 2021:001 | 725846469.184 | -6.5 | 21500.0 | nan | -8.393848298088113 | -8.342559970287693 | -8.30616855357068 | nan | nan | nan | False | False | True | 1 | 2 | 144.2 | False | 154.95 | False |
| aacccdpt | 2021:001 | 725846469.184 | -6.5 | 21500.0 | 47250.373802043854 | -7.154068151351936 | -6.790040553689484 | -6.5 | nan | nan | nan | True | False | False | 1 | 2 | 90.2 | False | 148.95 | False |
| aacccdpt | 2021:001 | 725846469.184 | -6.5 | 21500.0 | nan | -7.411729330402032 | -6.956815970804288 | -6.785451637474314 | nan | nan | nan | False | False | True | 2 | 1 | 50.0 | False | 140.0 | False |
| aacccdpt | 2021:001 | 725846469.184 | -6.5 | 21500.0 | nan | -0.012929127833614672 | 0.03814441333926601 | 0.10389656662600388 | nan | nan | nan | False | True | False | 1 | 2 | 90.0 | False | 100.0 | False |
| aacccdpt | 2021:001 | 725846469.184 | -6.5 | 21500.0 | nan | -3.2286628278301754 | -3.155946443627189 | -3.0047592290912712 | nan | nan | nan | False | True | False | 1 | 2 | 75.0 | False | 130.0 | False |
| aacccdpt | 2021:001 | 725846469.184 | -6.5 | 21500.0 | 41364.30588583145 | -7.6912126491687705 | -7.1312558604180865 | -6.5 | nan | nan | nan | True | False | False | 2 | 1 | 170.0 | False | 90.0 | False |
| aacccdpt | 2021:001 | 725846469.184 | -6.5 | 21500.0 | 10243.34267539528 | -6.897765606842965 | -6.7052851256062445 | -6.5 | nan | nan | nan | True | False | False | 1 | 2 | 90.0 | False | 170.0 | False |