diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..2007651 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,402 @@ +Attribution-NonCommercial-NoDerivatives 4.0 International + +======================================================================= + +Creative Commons Corporation ("Creative Commons") is not a law firm and +does not provide legal services or legal advice. Distribution of +Creative Commons public licenses does not create a lawyer-client or +other relationship. Creative Commons makes its licenses and related +information available on an "as-is" basis. Creative Commons gives no +warranties regarding its licenses, any material licensed under their +terms and conditions, or any related information. Creative Commons +disclaims all liability for damages resulting from their use to the +fullest extent possible. + +Using Creative Commons Public Licenses + +Creative Commons public licenses provide a standard set of terms and +conditions that creators and other rights holders may use to share +original works of authorship and other material subject to copyright +and certain other rights specified in the public license below. The +following considerations are for informational purposes only, are not +exhaustive, and do not form part of our licenses. + + Considerations for licensors: Our public licenses are + intended for use by those authorized to give the public + permission to use material in ways otherwise restricted by + copyright and certain other rights. Our licenses are + irrevocable. Licensors should read and understand the terms + and conditions of the license they choose before applying it. + Licensors should also secure all rights necessary before + applying our licenses so that the public can reuse the + material as expected. Licensors should clearly mark any + material not subject to the license. This includes other CC- + licensed material, or material used under an exception or + limitation to copyright. More considerations for licensors: + wiki.creativecommons.org/Considerations_for_licensors + + Considerations for the public: By using one of our public + licenses, a licensor grants the public permission to use the + licensed material under specified terms and conditions. If + the licensor's permission is not necessary for any reason--for + example, because of any applicable exception or limitation to + copyright--then that use is not regulated by the license. Our + licenses grant only permissions under copyright and certain + other rights that a licensor has authority to grant. Use of + the licensed material may still be restricted for other + reasons, including because others have copyright or other + rights in the material. A licensor may make special requests, + such as asking that all changes be marked or described. + Although not required by our licenses, you are encouraged to + respect those requests where reasonable. More considerations + for the public: + wiki.creativecommons.org/Considerations_for_licensees + +======================================================================= + +Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 +International Public License + +By exercising the Licensed Rights (defined below), You accept and agree +to be bound by the terms and conditions of this Creative Commons +Attribution-NonCommercial-NoDerivatives 4.0 International Public +License ("Public License"). To the extent this Public License may be +interpreted as a contract, You are granted the Licensed Rights in +consideration of Your acceptance of these terms and conditions, and the +Licensor grants You such rights in consideration of benefits the +Licensor receives from making the Licensed Material available under +these terms and conditions. + + +Section 1 -- Definitions. + + a. Adapted Material means material subject to Copyright and Similar + Rights that is derived from or based upon the Licensed Material + and in which the Licensed Material is translated, altered, + arranged, transformed, or otherwise modified in a manner requiring + permission under the Copyright and Similar Rights held by the + Licensor. For purposes of this Public License, where the Licensed + Material is a musical work, performance, or sound recording, + Adapted Material is always produced where the Licensed Material is + synched in timed relation with a moving image. + + b. Copyright and Similar Rights means copyright and/or similar rights + closely related to copyright including, without limitation, + performance, broadcast, sound recording, and Sui Generis Database + Rights, without regard to how the rights are labeled or + categorized. For purposes of this Public License, the rights + specified in Section 2(b)(1)-(2) are not Copyright and Similar + Rights. + + c. Effective Technological Measures means those measures that, in the + absence of proper authority, may not be circumvented under laws + fulfilling obligations under Article 11 of the WIPO Copyright + Treaty adopted on December 20, 1996, and/or similar international + agreements. + + d. Exceptions and Limitations means fair use, fair dealing, and/or + any other exception or limitation to Copyright and Similar Rights + that applies to Your use of the Licensed Material. + + e. Licensed Material means the artistic or literary work, database, + or other material to which the Licensor applied this Public + License. + + f. Licensed Rights means the rights granted to You subject to the + terms and conditions of this Public License, which are limited to + all Copyright and Similar Rights that apply to Your use of the + Licensed Material and that the Licensor has authority to license. + + g. Licensor means the individual(s) or entity(ies) granting rights + under this Public License. + + h. NonCommercial means not primarily intended for or directed towards + commercial advantage or monetary compensation. For purposes of + this Public License, the exchange of the Licensed Material for + other material subject to Copyright and Similar Rights by digital + file-sharing or similar means is NonCommercial provided there is + no payment of monetary compensation in connection with the + exchange. + + i. Share means to provide material to the public by any means or + process that requires permission under the Licensed Rights, such + as reproduction, public display, public performance, distribution, + dissemination, communication, or importation, and to make material + available to the public including in ways that members of the + public may access the material from a place and at a time + individually chosen by them. + + j. Sui Generis Database Rights means rights other than copyright + resulting from Directive 96/9/EC of the European Parliament and of + the Council of 11 March 1996 on the legal protection of databases, + as amended and/or succeeded, as well as other essentially + equivalent rights anywhere in the world. + + k. You means the individual or entity exercising the Licensed Rights + under this Public License. Your has a corresponding meaning. + + +Section 2 -- Scope. + + a. License grant. + + 1. Subject to the terms and conditions of this Public License, + the Licensor hereby grants You a worldwide, royalty-free, + non-sublicensable, non-exclusive, irrevocable license to + exercise the Licensed Rights in the Licensed Material to: + + a. reproduce and Share the Licensed Material, in whole or + in part, for NonCommercial purposes only; and + + b. produce and reproduce, but not Share, Adapted Material + for NonCommercial purposes only. + + 2. Exceptions and Limitations. For the avoidance of doubt, where + Exceptions and Limitations apply to Your use, this Public + License does not apply, and You do not need to comply with + its terms and conditions. + + 3. Term. The term of this Public License is specified in Section + 6(a). + + 4. Media and formats; technical modifications allowed. The + Licensor authorizes You to exercise the Licensed Rights in + all media and formats whether now known or hereafter created, + and to make technical modifications necessary to do so. The + Licensor waives and/or agrees not to assert any right or + authority to forbid You from making technical modifications + necessary to exercise the Licensed Rights, including + technical modifications necessary to circumvent Effective + Technological Measures. For purposes of this Public License, + simply making modifications authorized by this Section 2(a) + (4) never produces Adapted Material. + + 5. Downstream recipients. + + a. Offer from the Licensor -- Licensed Material. Every + recipient of the Licensed Material automatically + receives an offer from the Licensor to exercise the + Licensed Rights under the terms and conditions of this + Public License. + + b. No downstream restrictions. You may not offer or impose + any additional or different terms or conditions on, or + apply any Effective Technological Measures to, the + Licensed Material if doing so restricts exercise of the + Licensed Rights by any recipient of the Licensed + Material. + + 6. No endorsement. Nothing in this Public License constitutes or + may be construed as permission to assert or imply that You + are, or that Your use of the Licensed Material is, connected + with, or sponsored, endorsed, or granted official status by, + the Licensor or others designated to receive attribution as + provided in Section 3(a)(1)(A)(i). + + b. Other rights. + + 1. Moral rights, such as the right of integrity, are not + licensed under this Public License, nor are publicity, + privacy, and/or other similar personality rights; however, to + the extent possible, the Licensor waives and/or agrees not to + assert any such rights held by the Licensor to the limited + extent necessary to allow You to exercise the Licensed + Rights, but not otherwise. + + 2. Patent and trademark rights are not licensed under this + Public License. + + 3. To the extent possible, the Licensor waives any right to + collect royalties from You for the exercise of the Licensed + Rights, whether directly or through a collecting society + under any voluntary or waivable statutory or compulsory + licensing scheme. In all other cases the Licensor expressly + reserves any right to collect such royalties, including when + the Licensed Material is used other than for NonCommercial + purposes. + + +Section 3 -- License Conditions. + +Your exercise of the Licensed Rights is expressly made subject to the +following conditions. + + a. Attribution. + + 1. If You Share the Licensed Material, You must: + + a. retain the following if it is supplied by the Licensor + with the Licensed Material: + + i. identification of the creator(s) of the Licensed + Material and any others designated to receive + attribution, in any reasonable manner requested by + the Licensor (including by pseudonym if + designated); + + ii. a copyright notice; + + iii. a notice that refers to this Public License; + + iv. a notice that refers to the disclaimer of + warranties; + + v. a URI or hyperlink to the Licensed Material to the + extent reasonably practicable; + + b. indicate if You modified the Licensed Material and + retain an indication of any previous modifications; and + + c. indicate the Licensed Material is licensed under this + Public License, and include the text of, or the URI or + hyperlink to, this Public License. + + For the avoidance of doubt, You do not have permission under + this Public License to Share Adapted Material. + + 2. You may satisfy the conditions in Section 3(a)(1) in any + reasonable manner based on the medium, means, and context in + which You Share the Licensed Material. For example, it may be + reasonable to satisfy the conditions by providing a URI or + hyperlink to a resource that includes the required + information. + + 3. If requested by the Licensor, You must remove any of the + information required by Section 3(a)(1)(A) to the extent + reasonably practicable. + + +Section 4 -- Sui Generis Database Rights. + +Where the Licensed Rights include Sui Generis Database Rights that +apply to Your use of the Licensed Material: + + a. for the avoidance of doubt, Section 2(a)(1) grants You the right + to extract, reuse, reproduce, and Share all or a substantial + portion of the contents of the database for NonCommercial purposes + only and provided You do not Share Adapted Material; + + b. if You include all or a substantial portion of the database + contents in a database in which You have Sui Generis Database + Rights, then the database in which You have Sui Generis Database + Rights (but not its individual contents) is Adapted Material; and + + c. You must comply with the conditions in Section 3(a) if You Share + all or a substantial portion of the contents of the database. + +For the avoidance of doubt, this Section 4 supplements and does not +replace Your obligations under this Public License where the Licensed +Rights include other Copyright and Similar Rights. + + +Section 5 -- Disclaimer of Warranties and Limitation of Liability. + + a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE + EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS + AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF + ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, + IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, + WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR + PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, + ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT + KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT + ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. + + b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE + TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, + NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, + INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, + COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR + USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR + DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR + IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. + + c. The disclaimer of warranties and limitation of liability provided + above shall be interpreted in a manner that, to the extent + possible, most closely approximates an absolute disclaimer and + waiver of all liability. + + +Section 6 -- Term and Termination. + + a. This Public License applies for the term of the Copyright and + Similar Rights licensed here. However, if You fail to comply with + this Public License, then Your rights under this Public License + terminate automatically. + + b. Where Your right to use the Licensed Material has terminated under + Section 6(a), it reinstates: + + 1. automatically as of the date the violation is cured, provided + it is cured within 30 days of Your discovery of the + violation; or + + 2. upon express reinstatement by the Licensor. + + For the avoidance of doubt, this Section 6(b) does not affect any + right the Licensor may have to seek remedies for Your violations + of this Public License. + + c. For the avoidance of doubt, the Licensor may also offer the + Licensed Material under separate terms or conditions or stop + distributing the Licensed Material at any time; however, doing so + will not terminate this Public License. + + d. Sections 1, 5, 6, 7, and 8 survive termination of this Public + License. + + +Section 7 -- Other Terms and Conditions. + + a. The Licensor shall not be bound by any additional or different + terms or conditions communicated by You unless expressly agreed. + + b. Any arrangements, understandings, or agreements regarding the + Licensed Material not stated herein are separate from and + independent of the terms and conditions of this Public License. + + +Section 8 -- Interpretation. + + a. For the avoidance of doubt, this Public License does not, and + shall not be interpreted to, reduce, limit, restrict, or impose + conditions on any use of the Licensed Material that could lawfully + be made without permission under this Public License. + + b. To the extent possible, if any provision of this Public License is + deemed unenforceable, it shall be automatically reformed to the + minimum extent necessary to make it enforceable. If the provision + cannot be reformed, it shall be severed from this Public License + without affecting the enforceability of the remaining terms and + conditions. + + c. No term or condition of this Public License will be waived and no + failure to comply consented to unless expressly agreed to by the + Licensor. + + d. Nothing in this Public License constitutes or may be interpreted + as a limitation upon, or waiver of, any privileges and immunities + that apply to the Licensor or You, including from the legal + processes of any jurisdiction or authority. + +======================================================================= + +Creative Commons is not a party to its public +licenses. Notwithstanding, Creative Commons may elect to apply one of +its public licenses to material it publishes and in those instances +will be considered the “Licensor.” The text of the Creative Commons +public licenses is dedicated to the public domain under the CC0 Public +Domain Dedication. Except for the limited purpose of indicating that +material is shared under a Creative Commons public license or as +otherwise permitted by the Creative Commons policies published at +creativecommons.org/policies, Creative Commons does not authorize the +use of the trademark "Creative Commons" or any other trademark or logo +of Creative Commons without its prior written consent including, +without limitation, in connection with any unauthorized modifications +to any of its public licenses or any other arrangements, +understandings, or agreements concerning use of licensed material. For +the avoidance of doubt, this paragraph does not form part of the +public licenses. + +Creative Commons may be contacted at creativecommons.org. diff --git a/docs/backend-structures.md b/docs/backend-structures.md new file mode 100644 index 0000000..de3edd3 --- /dev/null +++ b/docs/backend-structures.md @@ -0,0 +1,236 @@ +The classes and functions contained in `base`. These objects form the internals of the structures and functioning of the rest of the objects a user would interact with. +> [!WARNING] +> This Wiki is not regularly updated. this page was last checked for accuracy on **8th December 2023**. +```mermaid + +classDiagram +direction RL + + class Variable{ + <> + +str identity + +base.NumType record + +str units + } + class HistoricVariable{ + <> + +str identity + +base.Iterable record + +str units + } + + + + class Vector { + <> + +str identity + +base.NumType X + +base.NumType Y + +base.NumType Z + +str units + } + class HistoricVector { + <> + +str identity + +base.HistoricVariable X + +base.HistoricVariable Y + +base.HistoricVariable Z + +str units + } + + class Body { + <> + } + + +HistoricVector <|-- Vector: subclass of Vector +HistoricVector <.. HistoricVariable: instances @ X, Y, Z +HistoricVariable <|-- Variable: subclass of Variable +Body <.. HistoricVector: instances @ pos, vel, acc +Body <.. Variable: instances @ mass, radius +``` +Above is a figure visualising how the structure of the `core` class [`Body`](https://github.com/will-roscoe/nbody/wiki/Core-Structures#corebodymassinit_posinit_vel000radius0bounce0999colornoneidentitynone) is formed from objects in this module. Each `base.HistoricVector` instance in `core.Body` represents a kinematic value describing the trajectory of the `Body`. + +Each `base.HistoricVector` instance is effectively comprised of 3 `base.HistoricVariable` instances, representing the components of the vector. The classes have solely been built for use in a 3D instance, but you may be able to use 2 dimensions inefficiently. + + +---- + + +## `base.Variable(init_var, identity='Variable', units=None)` +Basic single valued object with the ability to have an identity and units. Integrates with the rest of the `base` objects properly. +### Attributes: +|Attribute| Type| Description| +|---|---|---| +| `self.record` | [`base.NumType`](https://github.com/will-roscoe/nbody/wiki/Base-Structures#custom-type-definitions) | stores the x-component of the vector. | +| `self.identity` | `str` | identifier | +| `self.units` | `str` |units of the variable | +### Usage +#### `c()` + - Returns value of `Variable`. + - equivalent to `self.record`. + + +---- + + +## `base.HistoricVariable(init_var,identity='HistoricVariable',units=None)` +Subclass of `base.Variable`. single valued object that stores past values of the variable. Inherits the ability to have an identity and units. Integrates with the rest of the `base` objects properly. +### Attributes: +|Attribute| Type| Description| +|---|---|---| +| `self.record` | `list` | stores the current and past values of the variable. | +| `self.identity` | `str` | identifier | +| `self.units` | `str` |units of the variable| +### Usage +#### `c()` + - Returns latest value of `HistoricVariable`. + - equivalent to `self.record[-1]`. +#### `next(next_val)` + - Stores new current variable value by appending. + - equivalent to `self.record.append(next_val)`. +### Indexing + - Supports numerical indexing but not slicing. + +| Index | Returns| +|---|---| +|`'first'`, `'initial'`| initial value of variable| +|`'last'`, `'current'`| last value of variable| +|`'full'`, `'hist'`,`'all'`| all values of variable| +|`'past'`, `'old'`| all values excluding current value of variable| + + +---- + + +## `base.Vector(li=None,x=None,y=None,z=None)` +Object representing a 3-vector. Has the ability to have an identity and units, and integrates well with other `base` objects. Does not store any past values and is generally used for calculations using single points of data at a time. +### Attributes: +|Attribute| Type| Description| +|---|---|---| +| `self.X` | [`base.NumType`](https://github.com/will-roscoe/nbody/wiki/Base-Structures#custom-type-definitions) | stores the x-component of the vector. | +| `self.Y` | [`base.NumType`](https://github.com/will-roscoe/nbody/wiki/Base-Structures#custom-type-definitions) | stores the y-component of the vector. | +| `self.Z` | [`base.NumType`](https://github.com/will-roscoe/nbody/wiki/Base-Structures#custom-type-definitions) | stores the z-component of the vector. | +| `self.identity` | `str` | identifier | +| `self.units` | `str` |units of the vector components (homogenous across all components) | +### Usage +#### `c(ind=None)` + - Returns full tuple value of `Variable`. Alternative options for `ind` are: + * `0` --> x component, + * `1` --> y component, + * `2` --> z component. +#### `magnitude()` + + - Returns the magnitude (length) of the vector as a [`base.NumType`](https://github.com/will-roscoe/nbody/wiki/Base-Structures#custom-type-definitions) object. +#### `unit()` + - Returns the unit vector of the vector as a `base.Vector` object. + +#### `cross(other)` + - Returns the cross product of the vector and `other` as a `base.Vector` object. + * `other` must be an iterable object of length 3 or [`base.VectorType`](https://github.com/will-roscoe/nbody/wiki/Base-Structures#custom-type-definitions) object. +### Indexing + - Does not support Numerical indexing. +| Index | Returns| +|---|---| +|`'x'`, `'i'`| x-component of the vector.| +|`'y'`, `'j'`| y-component of the vector.| +|`'z'`, `'k'`| z-component of the vector.| +|`'current'`| tuple containing all components of the vector.| + + +---- + + +## `base.HistoricVector(x=None,y=None,z=None,li=None,identity=None,units_v=None)` +Subclass of `base.Vector`. Object representing a 3-vector, that stores past values of the variable whilst maintaining synchronity of length. Has the ability to have an identity and units, and integrates well with other `base` objects. Meant to be used such that it acts like a `base.Vector` until data is needing to be extracted for analysis/plotting. +### Attributes: +|Attribute| Type| Description| +|---|---|---| +| `self.X` | `base.HistoricVariable` | stores the x-component of the vector. | +| `self.Y` | `base.HistoricVariable` | stores the y-component of the vector. | +| `self.Z` | `base.HistoricVariable` | stores the z-component of the vector. | +| `self.identity` | `str` | identifier | +| `self.units` | `str` |units of the vector components (homogenous across all components) | + +### Usage +#### `x()` + - Returns the current x-component of the vector. +#### `y()` + - Returns the current x-component of the vector. +#### `z()` + - Returns the current x-component of the vector. +#### `c(ind=None)` + - Returns latest value of `HistoricVariable`. + - equivalent to `(self.x(), self.y(), self.z())`. Alternative options for `ind` are: + * `0` --> x component, + * `1` --> y component, + * `2` --> z component. + +#### `next(next_vals)` + - Stores new current value in each component Variable. + - equivalent to `self.record.append(next_val)` for each vector component. + - `next_vals` must be an iterable object of length 3 or `base.VectorType` object. +> [!NOTE] +> `HistoricVector` Inherits `magnitude()`, `unit()` and `cross()` from `Vector`, where current value (from `.c()`) is used. + + +### Indexing + - Supports numerical indexing and slicing. it will return a 2d array containing the vector values indexed in all components. + +| Index | Returns| +|---|---| +|`'x'`, `'i'`| current x-component of the vector.| +|`'y'`, `'j'`| current y-component of the vector.| +|`'z'`, `'k'`| current z-component of the vector.| +|`'current'`| tuple containing all components of the current vector.| +|`'first'`, `'initial'`| initial value of vector as a tuple| +|`'full'`, `'record'`,`'all'`| all values of vector as a 2d array.| +|`'past'`, `'old'`| all values excluding of vector as a 2d array, excluding the current value.| + + +---- + + +## `base.NullVector()` +Subclass of `base.Vector`. returns a `Vector`-similar instance with value `(0,0,0)`. + +---- + + +## Custom Type Definitions +|Type| Included| Description| +|---|---|---| +|`base.NoneType`|`type(None)`| type casted by a `None` object| +|`base.VarType`|`base.Variable`,`base.HistoricVariable`|0/1-Dimensional Scalar-Like Objects| +|`base.VectorType`|`base.Vector`,`base.HistoricVector`|3-Dimensional Array-Like Objects| +|`base.Iterable`|`list`,`tuple`,`numpy.ndarray`| common objects with iterable operations| +|`base.NumType`|`int`,`float`,`numpy.float32`, `numpy.float64`, `Decimal`| common numeric types| + +## Internal Helper Functions + +### `_O(obj)` + - Returns an 'opened' version of `obj`, i.e, it will return an instance of `obj` as a base python class or otherwise return obj as it was. It basically unpacks the current value from any `base` object to make it the same as its python base counterpart. + +### `_V(obj)` + - does the opposite of `_O`. it will always output a `base.VectorType` instance given the input is an `base.iterable` or already a `base.VectorType` instance. returns an error if a `str` or [`base.NumType`](https://github.com/will-roscoe/nbody/wiki/Base-Structures#custom-type-definitions) object is passed as `obj`. + +### `typecheck(argtype)` + - will raise an error if an item in argtype does not match up to its inputted type. + - argtype should be passed as a 2d tuple array containing sub-tuples with length 2. in position 0 a queryied item should be found and in position 2 should be a `type` instance, or tuple of `type` instances. + + - Example: + ```python + a, b, c = 3, 6.21, 'foo' + d, e = ('foo', 0.1), base.Vector((0,1,2)) + + typecheck(( + (a, int), # is a an int object + (b,(int, float, None)), # is b an int, float, or None + (c,str), # is c a string object + (d, (list,tuple)), # is d a list or tuple + (e, (None, *base.VectorType)) # is e None, or one of the types in VectorType + )) + # if all these are true, typecheck doesnt return, otherwise it will raise a TypeError. + ``` + + diff --git a/docs/jpl-horizons.md b/docs/jpl-horizons.md new file mode 100644 index 0000000..108df43 --- /dev/null +++ b/docs/jpl-horizons.md @@ -0,0 +1,88 @@ + +I have implemented part of the `astroquery` module to easily make simulations of objects on the JPL Horizons System, using `GET`/`POST` URL encoded requests. I have restricted the inputs to standardise the output for use in this project, but you should be able to get any body listed on the JPL Horizons System fairly easily. + +> [!NOTE] +> The content on this page is unlikely to change and is stable. + +## `horizons_query()` +Returns attributes from a single search query, i.e, 'Sun'. + ### Parameters + * `searchquery` (`str`) - object ID or identifiable name of object, ie, `'Sun'`. + * `observer` (`str`) - observer position ID. see JPL Horizons Manual for more info, default is `'0'` (Sun/Solar System Barycentric Centre). It is best to make this the reference object of your system. + * `time` (`str`) - time to get data from. **Note: You should keep this the same for all objects in a system.** format is in MJY (YYYY-MM-DD). + * `num_type` (`type`) - type of numerical to output information in, if needing high accuracy. Default is `float`. + * `return_type` (`str`) how to output the result, either as a `dict` (`'dict'`), `Body` (`'body'`) or printing the result (`'print'`). + +> [!TIP] +>In the case that the `searchquery` returns multiple unique objects, a list of objects should be outputted where you should enter the ID of your chosen object into the function instead. + + ### Returns + * This function will return a `Body` instance with the attributes of the queried object by default. + +## `horizons_batch()` +`horizons_batch` is a function that makes it easy to iterate over multiple objects using the same constants and return an iterable containing the result. Has the exact same arguments as `horizons_query()` except the input queries should be an iterable of `str` objects. + +## Examples: + +### Create an list of `Body` instances representing all the major bodies in the solar system. +```python +bodies = list(horizons_query(obj_id) for obj_id in ( + '10','199','299','399','499','599','699','799','899')) +``` +> [!TIP] +>this could actually be made more concise: +>```python +>bodies = horizons_batch(['10','199','299','399','499','599','699','799','899']) +>``` + +>```python +>print(bodies) +>``` +Returns: +>``` +>Querying "10" @JPL Horizons System +> ... +>Querying "899" @JPL Horizons System +>Getting data from JPL Horizons: 100%|█████████████████████████████████████████████████████████████████████████████| 9/9 [00:00<00:00, 98.66queries/s] +>[Body("Sun (10)", m=1.9885e+30, r=(...),v=(...)), a=(0, 0, 0)), +> ... +>Body("Neptune (899)", m=1.02409e+26, r=(...),v=(...)), a=(0, 0, 0))] +>``` +### Printing attributes of a body as `Decimal` and Querying using text: +> running this: would give us an error, +>```python +>from decimal import Decimal +>horizons_query('Pluto', num_type=Decimal, return_type='print') +>``` +>Returns: +>``` +>Querying "Pluto" @JPL Horizons System +>Traceback (most recent call last): +> ... +>ValueError: Ambiguous target name; provide unique id: +> ID# Name Designation IAU/aliases/other +> ------- ---------------------------------- ----------- ------------------- +> 9 Pluto Barycenter +> 999 Pluto 134340 +>``` +> The error is given as the horizons server picked up two possible objects that it could query, and cannot work out which one you wanted. +>instead, after the error we can choose the correct ID for the body we want to return, i.e, 999. +>```python +>horizons_query('999', num_type=Decimal, return_type='print') +>``` +>Returns: +>``` +>Querying "999" @JPL Horizons System +>Object: Pluto (999) +>*********** +>Mass: 13070000000000000000000.000 kg +>Radius: 1188300.0 m +>*********** +>position: (2436011869867.81494140625, -4641552098041.7890625, -250706318802.340087890625) (m) +>velocity: (24682.81863152435471420176327228546142578125, -21445.24496392483706586062908172607421875, -1503.5218150639748273533768951892852783203125)(ms^-1) +>*********** +>Query Date: 2023-11-03 +>``` + +> [!IMPORTANT] +> If you were to choose ''Pluto Barycenter'`, this would raise an exception as the function would not be able to find the mass or radius as a barycenter is not a physical object. diff --git a/docs/main-structures.md b/docs/main-structures.md new file mode 100644 index 0000000..be7bcfc --- /dev/null +++ b/docs/main-structures.md @@ -0,0 +1,202 @@ +> [!WARNING] +> This Wiki is not regularly updated. this page was last checked for accuracy on **8th December 2023**. +

+ +

+ +Above is a diagram representing how a set of 3 bodies' trajectories would be structured using `Body`, `Engine` and `mplVisual`. To make the animated output as efficient as possible we choose to simulate the objects in `Engine` before visualising it. + + + +---- + + +## `core.Body(mass,init_pos,init_vel=(0,0,0),radius=0,bounce=0.999,color=None,identity=None)` +This object is the representation of a single (solid) body with finite mass and size. Should be placed into an `core.Engine` instance to perform a simulation. +### Parameters +|Parameter| Required |Type| Description| +|---|---|---| ---| +|`mass` | ✓ | `base.NumType` | mass of the body in kg. | +|`init_pos` | ✓ | `base.Iterable` or `base.VectorType` | initial position of the body in m.| +|`init_vel` | ✕ | `base.Iterable` or `base.VectorType` | initial velocity of the body in ms^-1. Default is `(0,0,0)`.| +|`radius` | ✕ | `base.NumType` | radius of the body in m, modelled as a sphere. Default is `0`. if `radius=0`, collision physics will not be simulated, and will act as a point particle. | +|`bounce` | ✕ | `base.NumType` | coefficient of restitution for the body. the factor describing how much energy is lost in a collision. `1` will give perfect elastic collision, `0` will give a perfect inelastic collision. Default is `0.999`. | +|`color` | ✕ | `str` | color of the body when visualised. can used colors defined in matplotlib docs.| +### Attributes +|Attribute| Type| Description| +|---|---|---| +| `self.identity` |`str` | identifiable string to represent the body by. | +| `self.mass` |`base.Variable` | mass of the body. | +| `self.pos` |`base.HistoricVector` | positional vectors of body. | +| `self.vel` |`base.HistoricVector` | velocity vectors of body. | +| `self.acc` |`base.HistoricVector` | acceleration vectors of body. | +| `self.radius` |`base.Variable` | radius of the body. | +| `self.bounce` |`base.NumType` | coefficient of restitution used when the body is in a collision. | +| `self.color` |`str` | color of the body when visualised. | +### Usage +#### `update(dt=1,vel_change=None,acc_change=None,vel_next=None)` + - evaluates the bodies current position, velocity and acceleration, along with any optional changes, over a time interval `dt`. + +#### `_reinitialise(init_pos=None,init_vel=None)` + - resets the body to an initial position and length, erasing all other datapoints for position, velocity and acceleration. + +#### `get_(ind=-1, plotskip=0, c_mass=None, engine=None)` + - +### Indexing +- Supports numerical indexing but not slicing. + +| Index | Returns| +|---|---| +|`'pos'`| all points of position as a 2d array.| +|`'vel'`| all points of velocity as a 2d array.| +|`'acc'`| all points of acceleration as a 2d array.| +|`'current'`| 2d array containing the current position, velocity and acceleration.| +|`'info'`| dictionary containing all non kinematic properties of the body| +|`'x'`| 2d array containing all x components of position, velocity and acceleration vectors.| +|`'y'`| 2d array containing all y components of position, velocity and acceleration vectors.| +|`'z'`| 2d array containing all z components of position, velocity and acceleration vectors.| + + +---- + + + +## `core.Engine(dt=1,checking_range=3)` +This object acts as the physics engine, and simulates the gravitational effects of bodies, and can also simulate collisions as well. +### Parameters +|Parameter| Required |Type| Description| +|---|---|---| ---| +|`dt` | ✕ | `base.NumType` | interval in seconds between each datapoint in the simulation. Lowest will produce most accurate results. Default is `1`(second). | +|`checking_range` | ✕ | `int` | range of points to check for collisions over for each point. Default is `3`.| + +### Attributes +|Attribute| Type| Description| +|---|---|---| +| `self.bodies` |`list` | internal collection of bodies that have been attached. | +| `self.planes` |`list` | internal collection of planes that have been defined. | +| `self.fields` |`list` | internal collection of fields that have been defined. | +| `self.dt` |`base.NumType` | see `dt` above | +| `self.do_collisions` |`bool` | whether to calculate the effect of collisions with planes or other bodies when simulating the trajectories. Default=`True`. | +| `self.do_bodygravity` |`bool` | whether to calculate the effect of gravity due to other bodies when simulating the trajectories. Default=`True`.| +| `self.do_fieldgravity` |`bool` | whether to calculate the effect of fields when simulating the trajectories. Default=`True`.| + +### Usage +#### `attach_bodies(new_bodies)` + - attaches `core.Body` objects to the `Engine` instance. `new_bodies` must be passed as a `base.Iterable`. + +#### `save_as(dump='engine',file_name='nbody_data')` + - saves the current state and all child objects as an .npz file. + * `dump` = either `engine` or `bodies`, choosing to save engine with all children or just the `core.Bodies` objects. +#### `load_as(objects='engine',file_name='nbody_data')` + - loads the chosen file data into the `Engine` instance. `objects` = either `engine` or `bodies` and this specifies the target object(s) to load. +#### `make_relative_to(target_body)` + - reinitialises all bodies in the instance, changing the initial conditions so that `target_body` is located at (0,0,0) and the rest of the objects have the same initial conditions relative to `target_body`. +#### `create_acceleration(accel_vector)` + - creates a constant field of acceleration that can affect the simulated trajectories of bodies. + * `accel_vector` must be an iterable or `base.VectorType` instance. +>[!WARNING] +> if the value of an acceleration field or a body's velocity is sufficiently high, a body may fail to register a collision with a plane or another body. +> +> In these instances, it is neccesary to reduce `dt`. *(and increase `checking_range`, which will sample more points resulting in an earlier check collision being registered.)* +#### `create_plane(const_axis= 'z', const_val= 0)` + - creates an infinite plane with 0 thickness, parallel to a chosen euclidean plane. `const_axis` specifies the plane orientation, e.g, `'z'` would return a plane parallel to the x-y plane. `const_val` specifies the coordinate value it should be locked to. +#### `simulate(self,intervals)` + - runs a simulation over a specified amount of `intervals` (must be `int`). does not return anything, but each of the bodies will contain the new data, and the `Engine` instance can now be passed on to a `Visual` object to create an output. + + +---- + +## `core.mplVisual(engine,name='NBody Simulation (Matplotib)',show_info=False,show_grid=True,focus_body=None,do_picking=True,**kwargs)` +Object that outputs a visual, animated plot of an `core.Engine` instance, and can be customized to users preferences. +>[!NOTE] +The `core.Engine` instance should already have computed a simulation before insterting into a `mplVisual` instance. +### Parameters +|Parameter| Required |Type| Description| +|---|---|---| ---| +|`engine` | ✓ | `core.Engine` | engine containing the system that is to be visualized | +|`name` | ✕ | `str` | identifying name of the visual instance. | +|`show_info` | ✕ | `bool` | whether to show a description of live information of the `info_body`(Default: `focus_body`). Default: `False`.| +|`show_grid` | ✕ | `bool` | whether to draw the grid and grid faces of the plot. Default:`True`.| +|`focus_body` | ✕ | `core.Body` | body to keep in the center of the plot. If left as `None`, the plot will not center on a body. Default:`None`| +|`do_picking` | ✕ | `bool` | whether to enable object picking, allowing a user to choose a `focus_body` by clicking on the object, or `info_body` by clicking on the label or legend item.| +### `kwargs` +|Parameter|Type|Default| Description| +|---|---|---|---| +|`step_skip_frames` | `int` |`1` | the step to iterate over of frames. reduces the amount of frames in the final visual, but speeds up the animation. | +|`step_skip_points` | `int` | `1`| the step to iterate over of points. reduces the amount of points in each trail. eg: if `step_skip_frames=10`, and `step_skip_points=5`, each frame would contain 2 more points.| +|`fps` | `int` | `30`|framerate of the animation.| +|`max_pts` | `int` |`None` |maximum amount of points in each trail to plot. will remove oldest points if `max_pts` is exceeded.| +|`max_period` | `int` |`2` |maximum amount of periods for an object to draw until points are cut.| +||||| +|`vect_params` | `dict` |`{vel:False, acc:False, size:1}` | parameters to show acceleration and velocity vectors and a size scaling factor.| +|`speed_control` | `bool` |`False` |whether to enable a slider in the visual to control the speed.| +|`color_dict` | `dict` |`{line:'black', face:(0,0,0,0), bkgd:'white', text:'black'}` | color pallette used by the visual.| +|`focus_range` | `base.Numtype` | `None`|range to plot the grid around, given `focus_body` is not `None`. if `None`, the visual will autoscale, based on the furthest object.| +|`labelling_type` | `str` | `'legend'`|whether to use labels on objects or a legend. either `legend` or `labels`.| +|`body_model` | `str` |`'dots'` |how to draw the objects. can be `surface` or `wireframe` for spherical surface or `dots` as markers.| +||||| +|`info_body` | `core.Body` |`focus_body` |initial object to show information for.| +|`info_calc` | `bool` |`False` |whether to compute all info strings for objects for all frames prior to animation.| +|`anim_cache` | `bool` |`False` |see `matplotlib.animation.FuncAnimation` parameter `cache`.| +||||| +|`is_running` | `bool` |`True` |value used to toggle animation using play/pause button in visual.| +||||| +|`fmt_params` | `dict` | `?`|| +|`file` | `str` |`None` |where to save the `mplVisual` object. if `None` then the object is not saved.| +|`start_index` | `int` |`0` |index of bodies' data to begin animation at.| + +### Usage +#### `start(**viewparams)` + - function to start instances output window and animation. + - `viewparams`: parameters to pass to `axes.view_init()`. initial viewing parameters as `elev`, `azim`, `roll`. + +### Internals +below is a flowchart outlining the main internal structures of an `mplVisual` instance that come from the `matplotlib` library. you can use this to edit any parameters not defined already by an argument in `mplVisual` after it is initialised but before the `start()` function. all keyword arguments are stored as a dictionary as `self.args`. +```mermaid +flowchart RL + anim["`**self.anim** + *mpl.FuncAnimation*`"] + visual("`**self** + *mplVisual*`") + fig("`**self.fig** + *mpl.figure*`") + ax("`**self.ax** + *mpl.Axes3D*`") + z_ax("`**self.zoom_ax** + *mpl.Axes*`") + z_sl("`**self.zoom_slider** + *mpl.Slider*`") + s_ax("`**self.spd_ax** + *mpl.Axes*`") + s_sl("`**self.speed_slider** + *mpl.Slider*`") + pl_ax("`**self.plpa_ax** + *mpl.Axes*`") + pl_bt("`**self.playpause** + *mpl.Button*`") + arts(("`**Plotted Artists** + *mpl.Line3D, + mpl.Surface3D,etc*`")) + xax("`*mpl.XAxis*`") + yax("`*mpl.YAxis*`") + zax("`*mpl.ZAxis*`") + xax & yax & zax --> ax + pl_bt --> pl_ax + s_sl --> s_ax + z_sl --> z_ax + fig --> visual + anim <--> visual + ax --> fig + z_ax --> fig + s_ax -.-> fig + pl_ax --> fig + arts --> ax +``` +## Creating a `core.Body` From a Text File + +### The `body_from()` Function + +### Using a Text File + + + diff --git a/docs/other-structures.md b/docs/other-structures.md new file mode 100644 index 0000000..4bf4707 --- /dev/null +++ b/docs/other-structures.md @@ -0,0 +1,186 @@ +This page covers the following remaining miscellaneous objects and functions in this project: +- the `Formatter` class +- `io` functions: + * Structure of data files + * `obj_from()` - Importing data + * `export_data()` - Exporting Objects +> [!WARNING] +> This Wiki is not regularly updated. this page was last checked for accuracy on **8th December 2023**. +---- + +## The Formatter Class +### `text.Formatter(output_raw=False, items=('identity','mass','radius','energy','period','pos','vel','acc','time'), vector_pos=True, vector_vel=False, vector_acc = False, engine=None, plotskip=0, c_mass=0)` +Class used to format information about `core.Body` instances to be human readable and in useful units. Primarily used in the info readout in the `core.mplVisual` class. + +>[!NOTE] +It is possible to change the default units to convert to by changing lists that are found in the module code (`text.py`). + +### Useful Parameters +|Parameter| Required |Type| Description| +|---|---|---| ---| +|`output_raw` | ✕ | `bool` | whether to convert quanities or not. Default:`False`| +|`items` | ✕ | `tuple` | quantities to output to a string Default:`('identity','mass','radius','energy','period','pos','vel','acc','time')`(contains all possible quantities) | +|`vector_pos` | ✕ | `bool` | whether to output position as a magnitude or full vector. Default:`False`| +|`vector_vel` | ✕ | `bool` | whether to output velocity as a magnitude or full vector. Default:`False`| +|`vector_acc` | ✕ | `bool` | whether to output acceleration as a magnitude or full vector. Default:`False`| +|`engine` | ◑ | `core.Engine` | **Reqiured for outputting `time`**. Engine instance the body/ies of interest belong to. Default:`None`| +|`plotskip` | ◑ | `int` | **Reqiured for outputting `period` and `energy`**. effectively the `step_skip_frame` value of a `core.mplVisual` instance. Step used when calculating estimate over the bodies' positions. Default:`1`| +|`c_mass` | ◑ | `base.NumType` | **Reqiured for outputting `period`**. effectively the `major_body` value of a core.mplVisual instance. mass of largest body used when calculating estimate over the bodies' positions and mass. Default:`1`| + +### Useful Attributes +|Attribute| Type| Description| +|---|---|---| +| `self.target` |`list` | target body and index, needs to be assigned a value for valid output. Default:`[None, 0]` | + + + +### Usage +#### `convert(arg=None)` + - converts either `arg`(a dictionary with keys being in `items` and values as `pint.Quantity` instances), or target body and index into the ideal units, and outputs as a list of `pint.Quantity` instances, +#### `str(Formatter())` or `f'{Formatter()}'` + - returns a formatted string of the quantities for the target body and index. + + +### Example: +starting with an engine with an arbitrary number of bodies that has simulated some unknown system: +```python +phys = core.Engine(...) +phys.bodies = (core.Body(...), + ...) +``` +create a `Formatter` instance and assign a target body and index (here we will look at the first body and the last entry and we are only interested in the position as a vector and time): +```python +>>> info = text.Formatter(items=('identity','pos','time'), vector_pos=True, engine=None) +>>> info.target = [phys.bodies[0], -1] +``` +Finally, print the `Formatter` object as a string. +```python +>>> print(str(info)) +BodyName +pos: (123.56 m, 789.10 m, 111.213 m) +time: 12.53 a +``` +>[!NOTE] +The output units can sometimes be in non standard fractional units, for example a body with a mass equivalent to 0.0123 solar masses will output as 1.23 mM₀. + +---- + +## `io` functions +### 1. Structure of data files +an example of a text file for a set of bodies in an engine is below. +```python +# eng_info.txt + +dt = 1.23 +checking_range = 3 +# bodies:(2) +~ do_collisions = False +~ do_fieldgravity = True +~ do_bodygravity = True +*Obj_1 [ +name = object_name +mass = 1.4213 +radius = 23.124 +position = (6211, 6211.500, 6211.500) +] +*Obj_2 [ +name = object_name2 +mass = 2.0 +radius = 2.0 +position = (6212.57166, 6211.51, 6211.51) +] +-* plane = z = 3 +-* plane = x = 1 +-* field = (1,1,1) +-* rel = Obj_1 + +-* sim = 100 +``` +#### Prefixes +|Prefix | Usage | +|- | -| +|`~`|assigning attribute values| +|`*`|denoting a body| +|`-*` |calling functions| +|`#`| comments and supplementary data| +>[!NOTE] +Vectors or list like items must always use round parentheses. +#### Structuring a Body +a definition of a body begins with an identifier prefixed with an asterisk and all of its parameters then go inside a set of square brackets, the open on the same line as the identifier and the close on a separate line, directly after the last parameter: +``` +*{object_id} [ +{parameters} +] +``` +the following parameters can be defined for a Body: +```python +name[id, identity], mass, radius, position[pos], velocity[vel], color[colour], bounce. +# items in sq. brackets are alternative options. +``` +#### A Set of Positions +it is possible to pass a set of positions to create a body with past data as shown below: +```python +*Obj [ +name = object_name +mass = 1.4213 +position = ( # signified by curly brackets: +(1,2,3) # entry 1 +(4,5,6) # entry 2 +(7,8,9) # entry 3 +) # close position data +radius = 23.124 +] +``` +See the `obj_from()` function for information on parsing this type of format. +#### Defining Objects and Calling Functions for an Engine +It is possible to call specific functions relating to the `Engine` object that could be created, using the `-*` prefix as described before. There are 4 functions that can be called: +```python +-* plane = {const_axis} = {const_val} # see Engine.create_plane() + +-* field = ({x}, {y}, {z}) # see Engine.create_acceleration() + +-* rel = {object_id} # see Engine.make_relative_to() + +-* sim = {intervals} # see Engine.simulate() +``` +These must be ordered in a logical order, i.e. initialising planes before simultating otherwise the planes wouldn't exist at that point. +#### Basic ordering of File Contents +```mermaid +flowchart TD +subgraph body1 +b1p[Parameters] +end +subgraph body2 +b2p[Parameters] +end +subgraph ' +plane +field +end +engp[Engine Parameters] --- body1 --- body2 --- plane & field +plane & field --- rel --- sim +``` +---- +### 2. `obj_from(object, obj = 'engine')` +Function to parse a text file and create an object. +#### Parameters +- `object`: the text file containing the object data +- `obj` : parsing type, the type of object to find. + * must be one of: + - `'body'`: a body with standard data + - `'bodyext'`: a body with a sequence of positions + - `'engine'`: an engine with standard data +#### Returns +- either a `core.Engine` instance or `core.Body` instance. + +---- +### 3. `export_obj(object, loc, overwrite = False, info_name = None, csvs = True)` +Function to extract data from an object to a text file and optionally a csv per Body. if a `core.Engine` is input, it will export Body data as well for all bodies contained in it. +#### Parameters +- `object`: the object to get data from, can be a `core.Engine` instance or `core.Body` instance. +- `loc` : location or folder name to create with all data inside. +- `overwrite` : whether to overwrite files and folders. +- `info_name` : name of the text file (Optional). +- `csvs` : whether or not to export full pos, vel and acc data to a csv as well. +#### Returns +- `None`