0

I am trying to read an YAML file generated by a commercial software. An excerpt of test.yml looks like this:

%YAML 1.1 
---
VesselTypes:
  - Name: Tanker
    Length: 103
    Draughts:
      - Name: Draught1
        Mass: 9017.95
        MomentOfInertiaTensorX, MomentOfInertiaTensorY, MomentOfInertiaTensorZ:
          - [254.9374465E3, 1, 2]
          - [3, 5.979802645E6, 4]
          - [7, 8, 5.979802645E6]
          - [9, 10, 11]

Then, while parsing this file using python:

#filename: test.py
import yaml

with open('test.yml', 'r') as f:
        data = yaml.load(f)

print(data['VesselTypes'][0]['Draughts'][0]['Name'])

#This would work
print(data['VesselTypes'][0]['Draughts'][0]['MomentOfInertiaTensorX, MomentOfInertiaTensorY, MomentOfInertiaTensorZ'])

print('----------------------------------------------------')
#This would give error
print(data['VesselTypes'][0]['Draughts'][0]['MomentOfInertiaTensorX'])

Any suggestions on how the data are expected to be parsed? I just started learning YAML format, and python both, so a bit confused.

Anthon
  • 69,918
  • 32
  • 186
  • 246
Amitava
  • 431
  • 2
  • 6
  • 21
  • 2
    `'MomentOfInertiaTensorX, MomentOfInertiaTensorY, MomentOfInertiaTensorZ'`is the key to the matrix `[[254.9374465E3, 0, 0], ...]`. So the error is what you would expect! – Abdelhakim AKODADI Dec 13 '16 at 22:49
  • I expected them to be more useful than just information header. So to store the values as columns, now I need to run an iterative loop. – Amitava Dec 13 '16 at 23:47
  • I don't think the comma separated "unpacking" for keys is actually how YAML works. You'll probably need three lines like `MomentOfInertiaTensorX: [254.9374465E3, 0, 0]` etc. – Scott Colby Dec 13 '16 at 23:57
  • @ScottColby: The YAML file is generated by a commercial software. It seems that there is no other way than using the long key name to extract the data, and then use a for loop to extract columns. – Amitava Dec 14 '16 at 00:05
  • Oh! I missed the fact that this isn't your format. My apologies and condolences for having to deal with it. You probably won't need a for loop to extract though. See my answer below. – Scott Colby Dec 14 '16 at 00:11
  • This excerpt is an invalid YAML file, You cannot have a key-value pair at the top (`filename: test.yaml` followed by the version directive (`%YAML 1.1`). You should also update the software YAML version 1.2 has been out since 2009. Which commercial software is that? – Anthon Dec 14 '16 at 05:55
  • Your first attempt is the correct way how to get the value as `MomentOfInertiaTensorX, MomentOfInertiaTensorY, MomentOfInertiaTensorZ` is a single scalar string (which in YAML may contain spaces and commas). If the key had been `[MomentOfInertiaTensorX, MomentOfInertiaTensorY, MomentOfInertiaTensorZ]` then that would give you a list of three strings. Is that the case? – Anthon Dec 14 '16 at 05:56
  • @Anthon: The YAML file I am using is valid, its just that I put `filename: test.yaml` here while asking the question. The commercial software name is OrcaFlex, and we run a little behind in our industry with these updates. – Amitava Dec 14 '16 at 15:42
  • @Amitava If OrcaFlex writes/reads the YAML files with PyYAML then that would explain why they use this "fake" composite key instead of a real sequence, since PyYAML cannot load sequences as keys. – Anthon Dec 14 '16 at 15:51

1 Answers1

1

Extracting the lists without a loop using list unpacking.

x_moment, y_moment, z_moment = data['VesselTypes'][0]['Draughts'][0]['MomentOfInertiaTensorX, MomentOfInertiaTensorY, MomentOfInertiaTensorZ']
Scott Colby
  • 1,370
  • 12
  • 25
  • Thanks. But this stores values of first row to x_moment, second row to y_moment and third row to z_moment. I have updated my question so this is clear. Now do I need to use transpose or there is another way? – Amitava Dec 14 '16 at 00:55
  • Ah. If it's stored by column, you will need to transpose. Get the whole list-of-lists and use [this procedure](http://stackoverflow.com/a/6473724/600882) to do the transpose. If you're gonna be doing math on the values once you have them, it might be worth using the numpy solution also at that link and get everything into an array. – Scott Colby Dec 14 '16 at 00:58
  • 1
    Final answer: `import numpy as np` and then `x_moment, y_moment, z_moment = np.transpose(data['VesselTypes'][0]['Draughts'][0]['MomentOfInertiaTensorX, MomentOfInertiaTensorY, MomentOfInertiaTensorZ'])`. Thanks for help @Scott Colby. – Amitava Dec 14 '16 at 01:04