Showing posts with label an excerpt of which is shown below. Show all posts
Showing posts with label an excerpt of which is shown below. Show all posts

Dynamically creating python function



I am trying to parse a 10k line XML file with Python. The file, an excerpt of which is shown below, describes some physical properties of a long list of elements. Each element is described in the XML file by the "ble" element, and I already have Python classes written for each "ble" type I will encounter.



<header>
<!--SlotModels-->
<slotModels id="SpokeOptimusSlotModels" xml:base="spoke.xml" xmlns:xi="http://ift.tt/17F4Wja">
<slotModel id="spokeLEDP">
<var id="g1" type="double"/>
<ble id="DR0005" type="drift">
<d id="l" type="double" unit="mm">240</d>
<d id="r" type="double" unit="mm">20</d>
<d id="ry" type="double" unit="mm">0</d>
</ble>
<ble id="QD0020" model="Quad310" type="quad">
<d id="l" type="double" unit="mm">310</d>
<d id="g" type="double" unit="T/m">g1</d>
<d id="r" type="double" unit="mm">30</d>
</ble>
</slotModel>
<slotModel id="spokeLwu">
<var id="g1" type="double"/>
<ble id="DR0010" type="drift">
<d id="l" type="double" unit="mm">160</d>
<d id="r" type="double" unit="mm">30</d>
<d id="ry" type="double" unit="mm">0</d>
</ble>
<ble id="QD0020" model="Quad310" type="quad">
<d id="l" type="double" unit="mm">310</d>
<d id="g" type="double" unit="T/m">g1</d>
<d id="r" type="double" unit="mm">30</d>
</ble>
</slotModel>
<slotModel id="spokeCryomodule">
<var id="xelmax1" type="double"/>
<var id="rfpdeg1" type="double"/>
<ble id="DR0010" type="drift">
<d id="l" type="double" unit="mm">368.5</d>
<d id="r" type="double" unit="mm">28</d>
<d id="ry" type="double" unit="mm">0</d>
</ble>
<ble id="FM0020" model="spokeCavity" type="fieldMap">
<d id="rfpdeg" type="double" unit="deg">rfpdeg1</d>
<d id="xelmax" type="double" unit="unit">xelmax1</d>
<d id="radiusmm" type="double" unit="mm">28</d>
<d id="lengthmm" type="double" unit="mm">994</d>
<d id="file" type="string" unit="unit">Spoke_F2F</d>
<d id="scaleFactor" type="double" unit="unit">1.0</d>
</ble>
</slotModel>
</slotModels>
<slotModels id="medBetaSlotModels" xml:base="medBeta.xml" xmlns:xi="http://ift.tt/17F4Wja">
<slotModel id="medBetaLwu">
<var id="g1" type="double"/>
<ble id="DR0010" type="drift">
<d id="l" type="double" unit="mm">256.2</d>
<d id="r" type="double" unit="mm">50</d>
<d id="ry" type="double" unit="mm">0</d>
</ble>
<ble id="QD0020" model="Quad410" type="quad">
<d id="l" type="double" unit="mm">410</d>
<d id="g" type="double" unit="T/m">g1</d>
<d id="r" type="double" unit="mm">50</d>
</ble>
</slotModel>
<slotModel id="medBetaCryomodule">
<var id="xelmax1" type="double"/>
<var id="rfpdeg1" type="double"/>
<ble id="DR0010" type="drift">
<d id="l" type="double" unit="mm">414.4</d>
<d id="r" type="double" unit="mm">46.87</d>
<d id="ry" type="double" unit="mm">0</d>
</ble>
<ble id="FM0020" model="medBetaCavity" type="fieldMap">
<d id="rfpdeg" type="double" unit="deg">rfpdeg1</d>
<d id="xelmax" type="double" unit="unit">xelmax1</d>
<d id="radiusmm" type="double" unit="mm">46.87</d>
<d id="lengthmm" type="double" unit="mm">1258.8</d>
<d id="file" type="string" unit="unit">MB_F2F</d>
<d id="scaleFactor" type="double" unit="unit">1.0</d>
</ble>
</slotModel>
</slotModels>
<cellModels id="SpokeOptimusCellModels" xml:base="spoke.xml" xmlns:xi="http://ift.tt/17F4Wja">
<cellModel id="spokeLEDPCell">
<var id="g1" type="double"/>
<var id="xelmax1" type="double"/>
<var id="rfpdeg1" type="double"/>
<slot id="slot010" model="spokeLEDP">
<d id="g1" type="double">g1</d>
</slot>
<slot id="slot020" model="spokeCryomodule">
<d id="xelmax1" type="double">xelmax1</d>
<d id="rfpdeg1" type="double">rfpdeg1</d>
</slot>
</cellModel>
<cellModel id="spokeCell">
<var id="g1" type="double"/>
<var id="xelmax1" type="double"/>
<var id="rfpdeg1" type="double"/>
<slot id="slot010" model="spokeLwu">
<d id="g1" type="double">g1</d>
</slot>
<slot id="slot020" model="spokeCryomodule">
<d id="xelmax1" type="double">xelmax1</d>
<d id="rfpdeg1" type="double">rfpdeg1</d>
</slot>
</cellModel>
</cellModels>
<cellModels id="medBetaCellModels" xml:base="medBeta.xml" xmlns:xi="http://ift.tt/17F4Wja">
<cellModel id="medBetaCell">
<var id="g1" type="double"/>
<var id="xelmax1" type="double"/>
<var id="rfpdeg1" type="double"/>
<slot id="slot010" model="medBetaLwu">
<d id="g1" type="double">g1</d>
</slot>
<slot id="slot020" model="medBetaCryomodule">
<d id="xelmax1" type="double">xelmax1</d>
<d id="rfpdeg1" type="double">rfpdeg1</d>
</slot>
</cellModel>
</cellModels>
</header>
<linac>
<section id="SPOK" rfHarmonic="1" xml:base="spoke.xml" xmlns:xi="http://ift.tt/17F4Wja">
<cell id="cell010" model="spokeLEDPCell">
<d id="g1" type="double">5.23025</d>
<d id="g2" type="double">-4.68975</d>
<d id="xelmax1" type="double">0.868945</d>
<d id="xelmax2" type="double">0.865525</d>
<d id="rfpdeg1" type="double">-6.65943</d>
<d id="rfpdeg2" type="double">4.03247</d>
</cell>
<cell id="cell020" model="spokeCell">
<d id="g1" type="double">4.85226</d>
<d id="g2" type="double">-4.77927</d>
<d id="xelmax1" type="double">0.890626</d>
<d id="xelmax2" type="double">0.891124</d>
<d id="rfpdeg1" type="double">22.0298</d>
<d id="rfpdeg2" type="double">31.6618</d>
</cell>
<cell id="cell030" model="spokeCell">
<d id="g1" type="double">4.46164</d>
<d id="g2" type="double">-4.45154</d>
<d id="xelmax1" type="double">1</d>
<d id="xelmax2" type="double">1</d>
<d id="rfpdeg1" type="double">37.712</d>
<d id="rfpdeg2" type="double">47.397</d>
</cell>
<!--SPOKE-->
<section id="MBL" rfHarmonic="2" xml:base="medBeta.xml" xmlns:xi="http://ift.tt/17F4Wja">
<cell id="cell010" model="medBetaCell">
<d id="g1" type="double">3.39121</d>
<d id="g2" type="double">-3.31534</d>
<d id="xelmax1" type="double">0.44729</d>
<d id="xelmax2" type="double">0.4477</d>
<d id="xelmax3" type="double">0.453125</d>
<d id="xelmax4" type="double">0.453307</d>
<d id="rfpdeg1" type="double">55.8358</d>
<d id="rfpdeg2" type="double">61.7858</d>
<d id="rfpdeg3" type="double">66.1437</d>
<d id="rfpdeg4" type="double">72.2867</d>
</cell>
<cell id="cell020" model="medBetaCell">
<d id="g1" type="double">3.60124</d>
<d id="g2" type="double">-3.64339</d>
<d id="xelmax1" type="double">0.512886</d>
<d id="xelmax2" type="double">0.512886</d>
<d id="xelmax3" type="double">0.512886</d>
<d id="xelmax4" type="double">0.512886</d>
<d id="rfpdeg1" type="double">77.201</d>
<d id="rfpdeg2" type="double">84.17</d>
<d id="rfpdeg3" type="double">91.207</d>
<d id="rfpdeg4" type="double">98.296</d>
</cell>
</section>
</linac>


Note that the structure of the XML file is that the "slots" and "cells", which are basically lists of ble's with a discernable pattern, are defined in the header, while the data is kept in "linac".


What I would like to do


I would like to scan "linac", and expand each of the cells into a list of fully instantiated objects of the classes I have written to represent each of the ble's.


To do this, I would like to be able to parse the header in such a way that returns functions that can be called for each of the slotModels or cellModels. In other words, I would like to automatically generate functions something like the following:



def spokeLEDP(g1):
bleList = []
bleList.append(drift(l=240, r=20, ry=0)
bleList.append(quad(l=310, g=g1, r=30)
return bleList

def spokeLEDPcell(g1, xelmax1, rfpdeg1):
myList = []
myList.append(spokeLEDP(g1))
myList.append(spokeCryomodule(xelmax1, rfpdeg1))
return myList


I realise that I would need to flatten the list properly, but I hope you get the idea.


My plan


The only way I can currently see to proceed with dynamically generating the functions from the header, is a two step process. First, use Python to create a text file with the necessary functions. Then import this into the working code.


This seems very clunky and unwieldy.


My question


Is there a way to do what I want to do in one step, without a lot of repetitive parsing of the "cell" and "slot" elements in the XML header?


Many thanks for reading this far, and for any help you can offer.


(Note: I have no control over the structure of the XML file.)


Read more ...