Search code examples
pythonarraysnumpypydevmask

Does numpy.ma allow masking of sub-masked arrays in a masked array?


I am writing some code in Python 2.7 (using pydev in eclipse, Mac OSX) to gather information about a big set of card information stored in xml files. The cards are from Magic the gathering and all have a very similar card structure (Name, cost to play, type, etc.)

I am using masked arrays to store all of the information on the cards. Here is the array I initialize to store this information (more fields are added as they are encountered in the code):

AllCards=numpy.ma.masked_all(2, dtype=[('Set','a128'),('Name','a128'),
                                       ('Cost','a128'),('CMC','a128'), 
                                       ('Color','a128'),('Type','a128'),
                                       ('Subtype','a128'),('Rarity','a128'),
                                       ('Rules','a512'),('Power','a128'),
                                       ('Toughness','a128'),('PT Box','a128'),
                                       ('Artist','a128'),('Flavor','a512'),
                                       ('MultiverseId','a128')])

I have been able to populate and mask this array as I wanted, but I am running into a particular problem when I start to make this original array more complicated. When a card such as Faithful Squire, which has more complex components than a regular card (the flip aspect), it is coded in the xml as:

<card name="Faithful Squire" id="34905b29-481d-9e16-bc50-3b9f5a70dbf2">
  <property name="Cost" value="1ĄĄ" />
  <property name="CMC" value="3" />
  <property name="Color" value="White" />
  <property name="Type" value="Creature" />
  <property name="Subtype" value="Human Soldier" />
  <property name="Rarity" value="Uncommon" />
  <property name="Rules" value="Whenever you cast a Spirit or Arcane spell, you may put a ki counter on Faithful Squire.&#xD;&#xA;At the beginning of the end step, if there are two or more ki counters on Faithful Squire, you may flip it." />
  <property name="Power" value="2" />
  <property name="Toughness" value="2" />
  <property name="PT Box" value="2 / 2" />
  <property name="Artist" value="Mark Zug" />
  <property name="MultiverseId" value="74093" />
  <alternate name="Kaiso, Memory of Loyalty" type="flip">
    <property name="Cost" value="1ĄĄ" />
    <property name="CMC" value="3" />
    <property name="Color" value="White" />
    <property name="Type" value="Legendary Creature" />
    <property name="Subtype" value="Spirit" />
    <property name="Rarity" value="Uncommon" />
    <property name="Rules" value="Flying&#xD;&#xA;Remove a ki counter from Kaiso, Memory of Loyalty: Prevent all damage that would be dealt to target creature this turn." />
    <property name="Power" value="3" />
    <property name="Toughness" value="4" />
    <property name="PT Box" value="3 / 4" />
    <property name="Artist" value="Mark Zug" />
    <property name="MultiverseId" value="74093" />
  </alternate>
</card>

All of the propertys of the top-level card object are the fields, so my intention is to create another masked array that holds the properties of "flip" cards, so all the flip cards can be categorized as such (and properties analyzed, etc.) I am able to create a masked array of these properties, and append it as a field to the larger array using:

AllCards=numpy.lib.recfunctions.append_fields(AllCards,AlternateCardType,AlternateCard) 

but when I try to update the mask using:

AllCards.mask[AlternateCardType][0]=True

I receive the following error:

Traceback (most recent call last):
    File "/Applications/Eclipse/plugins/org.python.pydev_2.7.3.2013031601/pysrc/pydevd.py", line 1397, in <module>
        debugger.run(setup['file'], None, None)
    File "/Applications/Eclipse/plugins/org.python.pydev_2.7.3.2013031601/pysrc/pydevd.py", line 1090, in run
        pydev_imports.execfile(file, globals, locals) #execute the script
    File "/Users/Andrew/Documents/Workspace/PyGather/PyGather.py", line 61, in <module>
        !AllCards.mask[AlternateCardType][0]=True
TypeError: expected a readable buffer object

before this sub masked array is in the top-level array, I am able to manipulate the mask as such, and can use loops and assignments to mask items I don't want. I am trying to mask this because numpy.lib.recfunctions.append_fields automatically adds the data to the first item in the array, and I couldn't figure out how to pad the data appropriately. Is this a bug, or am I doing something wrong in the code!

Full Source


Solution

  • I did fix my problem by actually thinking about what I was passing. The shape of the sub-array was something like (A,B,C,D...). What you pass a mask, it should be of the same structure, so I was trying to assign True to a tuple. When I tried using (True,True,True...) it worked!