Skip to content
theodox edited this page Feb 28, 2016 · 17 revisions

A minq Stream represents an arbitrary stream of values. Usually -- but not always -- this is a stream of Maya node names. Usually -- but not always -- this stream is a 'stored query', like a SQL statement: it's not a list of saved values but rather a chain of operations. This allows you to manipulate queries themselves, rather than their contents.

Streams can be combined using set-like operators:

stream1 + stream2

returns a new stream containing the combined contents of both streams (duplicate values are removed)

stream1 - stream2

returns items that are only present in stream1 and not stream2

stream1 & stream2

returns only items that are common to both streams.

Most streams are created by a NodeType-derived class: for example, Meshes() will yield all of the poly meshes in the scene as a Stream, while Transforms() will yield all the transforms. However you can 'initialize' a stream with a list or tuple if you already know the names of nodes or objects you're looking for: for example,

Cameras()

and

Stream(['topShape', 'frontShape', 'perspShape', 'sideShape])

are functionally interchangeable in a typical maya scene.

Methods

Every stream offers the following methods:


###Filtering

These methods are used to narrow the scope of a stream by removing objects based on name, attribute values or other criteria.

####only(*object_types, namespace=None) Returns a new stream containing only items of the supplied types. The types can be string typenames (such as 'transforms' or 'shapes') or they can be minq.core.NodeType classes. So

   this_stream.only('transform')

and

   this_stream.only(Transform)

are equivalent.

A handful of special NodeTypes (such as ObjectsOnly or Assemblies) can't be combined with others in a single call. If you try to use one of those as part of a single only() a minq will raise a QueryException.

if the optional namespace keyword is passed, this limits the stream to a given namespace. You can use with with or without a node type filter:

    my_stream.only(Meshes, namespace='character1')
    character2_root = Assemblies().only(namespace = 'character2').first()

####where(filter_function) Given a callable filter function, returns a new stream containing only items for which the filter function return a truth-tested value.

    def too_large_to_export (obj):
        return cmds.polyEvaluate(obj, v=True) > 16535

    non_exportable = Meshes().where(too_large_to_export)

where supports a special factory class to generate some kinds of test functions for you (see [minq.item] for more details).

     above_origin = Transforms.where(item.tx >= 0)

####where_not( filter_function) a convenience wrapper for 'where' that inverts the result -- useful for not having to make a lambda just to invert a common function

####having( attrib) Returns a stream of objects with the supplied attribute. For example

	Transforms().having('attrib_name')

returns only transform nodes with the a custom attribute named attrib_name. This is equivalent to cmds.ls("*.attrib_name", o=True)

####like(regex, exact=False) Given a string regular expression, returns a new stream containing only items where the regex finds a match. By default this allows subset metches using re.search, but if the optional 'exact' flag is set to True, the matches must be complete using re.match

If the incoming stream contains items that can't be converted to strings, will raise an exception

Expanding and transforming streams

####foreach(func) Returns a stream containing the results of func applied to everything in the stream. Func may return any kind of value, so there's not guarantee that the resulting stream will contain only maya objects; depending on the usage that may be what you want.

For PyMel users, stream.foreach(PyNode) will return the results of a query as PyNodes, rather than maya strings.

####get(*args, **kwargs) Returns a new stream which replaces the incoming stream with a new stream (rather than subsetting the original stream). For example:

   transforms.get(Children)

returns a streams containing the children of the stream .

Valid operations for get() are defined in the [minq.Projections] submodule. The most common ones are:

: Children: The immediate children of the current stream

: Parents: The immediate parents of the current stream

: AllChildren: Everything in the Maya DAG below the contents of the current stream

: AllParents: Everything in the Maya DAG above the contents of the current stream

: History: The upstream history for everything in the current stream

: Future: The downstream history for everything in the current Stream

: Connections: All of the DAG connections for the everything in the current stream

####append(*args, **kwargs) Takes the same arguments as get(), but rather than replacing the current stream it appends the results to the existing stream.

Stream management

These functions are used to manage streams.

####cache() returns a Stream wrapped around a the cached result of this query.

####distinct() Returns a new stream which contains no duplicate elements. If the incoming stream contains items that can't be hashed, will raise an exception

####execute() Evaluate all of the queries in this Stream and return the result as a list. It's more idiomatic to use list(your_stream) but it is sometimes helpful to be certain exactly when a query will be fired off.

####first() Returns the first item in this stream as a single value (not a stream)

####flatten() Turns a stream containing multiple iterables (for example, the result of a get()) into a single stream.

####split(number_of_streams) Returns multiple 'copies' of this stream which can be iterated independently without re-calling the query. This is especially handy in conjunction with join()

####join(**streams) given a collection of named streams, return a table-like stream in which each 'row' has named values corresponding to the original stream. This is used for coordinating multiple streams: for example:

    bones = Joints()
    bone_parents = bones.get(Parents)
    with_parents = bones.join(parent = bone_parents)

will produce a list like

   # stream: [dataRow(object=u'joint3', parent=u'joint2'), dataRow(object=u'joint2', parent=u'joint1')....]

the join process doesn't make any effort to match up the contents, however -- if the different streams have different lengths enmpy 'columns' in the row will be filled with None and if the streams don't match up the results are not predictable.

The primary use for join() is for doing bulk queries using Attributes:

   bones = Joints().like('l_')
   tx = bones.get(Attribute, 'tx').get(Values)
   ty = bones.get(Attribute, 'ty').get(Values)
   bone_translations = bones.join(x = tx, y = ty)
   print bone_translations

  # stream: [dataRow(object=u'L_Ankle', x=-5.0, y=-1.39), dataRow(object=u'L_Heel', x=-0.028, y =6.18)....]

Note in this specific case it would be faster to use .get(Attribute, 't') rather than querying .tx and .ty separately -- but this pattern works for any arbitrary combination of attributes as long as all the objects in the stream have the attribute. In this form the query is issued to maya only once per stream, which is a big advantage over individually calling getAttr many times over.

Formatting

These functions format the output of the stream. By default minq always returns long names, but depending on the operations you try

####long(self) Returns a new stream containing the long names of items in this stream. Any items which are not maya nodes in the stream will be filtered out.

####short(self) Returns a new stream containing the short names of items in this stream. Any items which are not maya nodes in the stream will be filtered out.

####sort(key) returns a Stream which sorts the incoming stream using the default Python sort. If the optional key function is provided, the result will be sorted with that key.

This operation has to exhaust the incoming stream, so it is more memory and performance intensive than other minq operations.

####uuid(self) Returns a new stream containing the uuids of items in this stream. Any items which are not maya nodes in the stream will be filtered out.

Clone this wiki locally