======================= ``grail.mstype`` Module ======================= .. include:: ..\version.h .. contents:: Table of Contents :backlinks: top -------- Overview -------- The ``grail.mstype`` module was designed to improve the handling of large point and face data throughout the MSGRAIL system. In general, the ``mstype`` module should *just work* without you having to do much to make it work. In general, the **mstypes** will work in all cases, except for a single `Known Issue`_. It is recommended that all new scripts enable **mstypes**. To allow for backward compatibility concerns, the **mstypes** are disabled by default. To enable **mstypes** you must insert the following line into your script, .. Python:: import grail.mstype_enable this convenience module will automatically rewire the underlying mechanics with point and face data within MSGRAIL and MineSight(r) to use **mstypes**. This module also provides a set of Functions_ that allow you to transform your data from the new **mstypes** to the older format, and vicea versa. ------- Details ------- Prior to v4.00 of MSGRAIL all point data (and face data) were transformed from their efficient underlying binary structure to a less efficient Python structure. This lead to unnecessary performance penalities if you were passing point data from one MSGRAIL function to another. For example, the following call will result in too many unneccessary conversion, .. Python:: points = el.get_pointlist() # (1) Binary -> Python itIs = ag.ispointlistaline(points) # (2) Python -> Binary In line 1, we would convert binary data to a python point list, followed by a reconversion back to the original binary data in line 2. The purpose of **mstypes** is to remove the reconversion process. If **mstypes** are enabled, you will end up passing a reference to the underlying binary data, and the binary data will only be convert *at the moment you need a python list*. Even then, the conversion will only occur if you decide to do something with the **mstype** that doesn't make sense (for example, attempting to insert a string into a point list). In essesence we are delaying the conversion from binary data to a python list to the very last moment. For convenience, we provide a module that you can import to automatically enable **mstypes** in your script. If you do the following, .. Python:: import grail.mstype_enable you will automatically enable **mstypes**. The above call effectively does the following, .. Python:: import grail.mstype grail.mstype.Enable() --------- Functions --------- Controlling Mstypes ------------------- .. Note:: If you are using the convenience ``import grail.mstype_enable`` idiom, mixing the following calls in your script should be done carefully. :df:`Disable()` Call this function to disable **mstypes** in the MineSight(r) system. :df:`Enable()` Call this function to enable **mstypes** in the MineSight(r) system. :df:`Is_Enabled()` Call this function to determine if **mstypes** are enabled within the MineSight(r) system. :df:`Set_Enabled_State(is_on)` Will set the state of the **mstypes** based on the value of the :a:`is_on` argument. Conversion ---------- :df:`As_Py(obj)` This function will convert :a:`obj` to a pure python representation, and remove any notion of **mstypes**. It can be considered the universal *escape hatch*. Point Lists ----------- :df:`PointList_Check(obj)` Returns true if :a:`obj` is a point list. The :a:`obj` can either be a pure python list or a **mstype**. :df:`PointList(obj)` Converts the :a:`obj` to a **mstype** pointlist. :df:`PointList_YZSwap(obj)` This will perform a YZSwap on the points in :a:`obj`. It will return a *new copy* of :a:`obj` with all its coordinates swapped. If you do not want to duplicate memory you should perfer to use the :f:`nPointList_YZSwap` described below. An example of using this routine is, .. Python:: >>> from grail import mstype >>> pointList = [[1, 2, 3], [10, 20, 30], [100, 200, 300]] >>> swapped = mstype.PointList_YZSwap(pointList) >>> print pointList [[1, 2, 3], [10, 20, 30], [100, 200, 300]] >>> print swapped [[1, 3, 2], [10, 30, 20], [100, 300, 200]] as you can see, the original point is not modified. :df:`nPointList_YZSwap(obj)` Occasionally you will stumble across a routine that needs to swap coordinates from XYZ (cartesian coordinate space) to XZY (graphical coordinate space), this routine will efficiently swap the Y and Z coordinates. The change will modify the contents of :a:`obj`. For example, .. Python:: >>> from grail import mstype >>> pointList = [[1, 2, 3], [10, 20, 30], [100, 200, 300]] >>> mstype.nPointList_YZSwap(pointList) >>> print pointList [[1, 3, 2], [10, 30, 20], [100, 300, 200]] and if we re-run the routine we will get back our original point list. .. Python:: >>> mstype.nPointList_YZSwap(pointList) >>> print pointList [[1, 2, 3], [10, 20, 30], [100, 200, 300]] If the :a:`obj` is not a valid pointlist a :e:`TypeError` exception will be generated. See also `Efficiently Swapping Y and Z Coordinates`_ in the HowTo_. .. _HowTo: ../HowTo/index.html .. _Efficiently Swapping Y and Z Coordinates: ../HowTo/howto-efficiently-swap-yz.html Point ----- :df:`Point_Check(obj)` Returns true if :a:`obj` is a point. The :a:`obj` can either be a pure python list or a **mstype**. :df:`Point(obj)` Converts the :a:`obj` to a **mstype** point. :df:`Point_YZSwap(obj)` Performs a YZSwap of :a:`obj`, but returns a *new* point without modifiying the original. If you want to efficiently modify the contents *in place* use :f:`nPoint_YZSwap`. An example of using this routine is, .. Python:: >>> from grail import mstype >>> point = [1, 2, 3] >>> swapped = mstype.Point_YZSwap(point) >>> print point [1, 2, 3] >>> print swapped [1, 3, 2] :df:`nPoint_YZSwap(obj)` Occasionally you will stumble across a routine that needs to swap coordinates from XYZ (cartesian coordinate space) to XZY (graphical coordinate space), this routine will efficiently swap the Y and Z coordinates. The change will modify the contents of :a:`obj`. For example, .. Python:: >>> from grail import mstype >>> point = [1, 2, 3] >>> mstype.nPoint_YZSwap(point) >>> print point [1, 3, 2] If the :a:`obj` is not a valid point a :e:`TypeError` exception will be generated. See also `Efficiently Swapping Y and Z Coordinates`_ in the HowTo_. Face List --------- :df:`FaceList_Check(obj)` Returns true if :a:`obj` is a face list. The :a:`obj` can either be a pure python list or a **mstype**. :df:`FaceList(obj)` Converts the :a:`obj` to a **mstype** face list. ----------- Known Issue ----------- .. DOC NOTE: Right now there is only one Known Issue, but if there .. are others, uncomment the following lines to give this section a .. little more of a description. .. The following section indicate the known issues with the **mstypes**. .. Most of the time, if you start your *new* script using **mstypes**, you .. should be able to avoid these issues. Using :f:`type()` on a **mstype** will not return a :d:`ListType` ----------------------------------------------------------------- If you do the following when **mstypes** are enabled, .. Python:: type(aPointList) it will not be equal to a python :d:`types.ListType`. Some old scripts used the following test, .. Python:: type(aPointList) == types.ListType to ensure that they are getting valid data. It is recommended that you replace the above test with, .. Python:: import mstype mstype.PointList_Check(aPointList) which will confirm that :d:`aPointList` is in fact a pointlist, even if it is a **mstype**. The same issues apply to a point and facelist, where it is recommended that you use the :f:`Point_Check` and :f:`FaceList_Check` respectively.