def testConfiguration(self): channel = 'masarService' self.mc = masarClient.client(channelname=channel) # DB SETUP self.conn, collection = utils.conn( host=masarconfig.get('mongodb', 'host'), port=masarconfig.get('mongodb', 'port'), db=masarconfig.get('mongodb', 'database')) self.conn.drop_database(masarconfig.get('mongodb', 'database')) name = "SR_All_20140421" test_status = 'active' test_version = 20140421 test_system = 'SR' test_desc = "SR daily SCR setpoint without IS kick and septum: SR and RF" params = { "desc": test_desc, "system": test_system, "status": test_status, "version": test_version, } newid = saveconfig(self.conn, collection, name, **params) self.assertNotEqual(None, newid) res0 = retrieveconfig(self.conn, collection, name) self.assertEqual(test_status, res0[0]['status']) self.assertEqual(1, res0[0]['configidx']) self.assertEqual(name, res0[0]['name']) self.assertEqual(test_system, res0[0]['system']) self.assertNotEqual(None, res0[0]['created_on']) # The following 2 tests are to confirm the date string is in the correct format self.assertEqual(3, len(res0[0]['created_on'].split('-'))) self.assertEqual(3, len(res0[0]['created_on'].split(':'))) self.assertEqual(test_version, res0[0]['version']) self.assertEqual(test_desc, res0[0]['desc']) pvs = ["masarExampleDoubleArray"] pvlist = {"names": pvs} res = updateconfig(self.conn, collection, name, pvlist=pvlist) self.assertEqual(True, res) res3 = retrieveconfig(self.conn, collection, name, withpvs=True) self.assertEqual(test_status, res3[0]['status']) self.assertEqual(1, res3[0]['configidx']) self.assertEqual(name, res3[0]['name']) self.assertEqual(test_system, res3[0]['system']) self.assertNotEqual(None, res3[0]['created_on']) # The following 2 tests are to confirm the date string is in the correct format self.assertEqual(3, len(res3[0]['created_on'].split('-'))) self.assertEqual(3, len(res3[0]['created_on'].split(':'))) self.assertEqual(test_version, res3[0]['version']) self.assertEqual(test_desc, res3[0]['desc']) self.assertEqual(pvlist, res3[0]['pvlist']) self.assertNotEqual(None, res3[0]['updated_on']) # The following 2 tests are to confirm the date string is in the correct format self.assertEqual(3, len(res3[0]['updated_on'].split('-'))) self.assertEqual(3, len(res3[0]['updated_on'].split(':'))) # drop DB self.conn.drop_database(masarconfig.get('mongodb', 'database')) utils.close(self.conn)
def testConfiguration(self): channel = 'masarService' self.mc = masarClient.client(channelname=channel) # DB SETUP self.conn, collection = utils.conn(host=masarconfig.get('mongodb', 'host'), port=masarconfig.get('mongodb', 'port'), db=masarconfig.get('mongodb', 'database')) self.conn.drop_database(masarconfig.get('mongodb', 'database')) name = "SR_All_20140421" test_status = 'active' test_version = 20140421 test_system = 'SR' test_desc = "SR daily SCR setpoint without IS kick and septum: SR and RF" params = {"desc": test_desc, "system": test_system, "status": test_status, "version": test_version, } newid = saveconfig(self.conn, collection, name, **params) self.assertNotEqual(None, newid) res0 = retrieveconfig(self.conn, collection, name) self.assertEqual(test_status, res0[0]['status']) self.assertEqual(1, res0[0]['configidx']) self.assertEqual(name, res0[0]['name']) self.assertEqual(test_system, res0[0]['system']) self.assertNotEqual(None, res0[0]['created_on']) # The following 2 tests are to confirm the date string is in the correct format self.assertEqual(3, len(res0[0]['created_on'].split('-'))) self.assertEqual(3, len(res0[0]['created_on'].split(':'))) self.assertEqual(test_version, res0[0]['version']) self.assertEqual(test_desc, res0[0]['desc']) pvs = ["masarExampleDoubleArray"] pvlist = {"names": pvs} res = updateconfig(self.conn, collection, name, pvlist=pvlist) self.assertEqual(True, res) res3 = retrieveconfig(self.conn, collection, name, withpvs=True) self.assertEqual(test_status, res3[0]['status']) self.assertEqual(1, res3[0]['configidx']) self.assertEqual(name, res3[0]['name']) self.assertEqual(test_system, res3[0]['system']) self.assertNotEqual(None, res3[0]['created_on']) # The following 2 tests are to confirm the date string is in the correct format self.assertEqual(3, len(res3[0]['created_on'].split('-'))) self.assertEqual(3, len(res3[0]['created_on'].split(':'))) self.assertEqual(test_version, res3[0]['version']) self.assertEqual(test_desc, res3[0]['desc']) self.assertEqual(pvlist, res3[0]['pvlist']) self.assertNotEqual(None,res3[0]['updated_on']) # The following 2 tests are to confirm the date string is in the correct format self.assertEqual(3, len(res3[0]['updated_on'].split('-'))) self.assertEqual(3, len(res3[0]['updated_on'].split(':'))) # drop DB self.conn.drop_database(masarconfig.get('mongodb', 'database')) utils.close(self.conn)
def testUpdateMasarConfigStatus(self): app = QtGui.QApplication(sys.argv) ui = dbmanagerUI() ui.dbsource = 1 # Called normally with menu selection ui.defaultmongodb() masarconf = 'SR_All_20140421' conn, collection = utils.conn(host=masarconfig.get('mongodb', 'host'), port=masarconfig.get('mongodb', 'port'), db=masarconfig.get('mongodb', 'database')) ui.updatemasarconfigstatus("inactive", 1) res3 = retrieveconfig(conn, collection, masarconf, withpvs=True) self.assertEqual("inactive", res3[0]['status']) ui.updatemasarconfigstatus("active",1) res3 = retrieveconfig(conn, collection, masarconf, withpvs=True) self.assertEqual("active", res3[0]['status'])
def testRetrieveSnapshot(self): name = 'SR-All-20140326' test_comment = "test" test_approval = True test_username = "******" test_masar_data = [0] params = { "desc": "SR daily SCR setpoint: SR and IS PS, RF", "system": "SR", "status": "inactive", "version": 20140326, } newid = saveconfig(self.conn, self.collection, name, **params) new = retrieveconfig(self.conn, self.collection, name=name) self.assertEqual(len(new), 1, "Should find only one entry instead of %s" % len(new)) configidx = new[0]["configidx"] eventid = saveevent(self.conn, self.collection, configidx=configidx, comment=test_comment, approval=test_approval, masar_data=test_masar_data, username=test_username) self.assertNotEqual(eventid, None) result = retrievesnapshot(self.conn, self.collection, eventidx=eventid) self.assertEqual(result["eventidx"], eventid) self.assertEqual(result["configidx"], configidx) self.assertEqual(result["comment"], test_comment) self.assertEqual(result["approval"], test_approval) self.assertEqual(result["username"], test_username) self.assertEqual(result["masar_data"], test_masar_data)
def retrieveChannelNames(self, params): """Retrieve PV name list of given configuration(s). :param params: a dictionary to carry query condition with structure like: :: {"configname": , # configuration name, wildcast allowed with * for multiple characters matching } :returns: list of pv name like: :: [pv1, pv2, ...] :raises: ValueError """ key = ['configname', "comment"] config, _ = self._parseParams(params, key) if config is not None: mongoconn, collection = utils.conn(host=os.environ["MASAR_MONGO_HOST"], port=os.environ["MASAR_MONGO_PORT"], db=os.environ["MASAR_MONGO_DB"]) result = pymasar.retrieveconfig(mongoconn, collection, name=config, withpvs=True) utils.close(mongoconn) else: raise ValueError("Known configuration name.") results = [] for res in result: results = results + res["pvlist"]["names"] return results
def testUpdateMasarConfigStatus(self): app = QtGui.QApplication(sys.argv) ui = dbmanagerUI() ui.dbsource = 1 # Called normally with menu selection ui.defaultmongodb() masarconf = 'SR_All_20140421' conn, collection = utils.conn(host=masarconfig.get('mongodb', 'host'), port=masarconfig.get('mongodb', 'port'), db=masarconfig.get( 'mongodb', 'database')) ui.updatemasarconfigstatus("inactive", 1) res3 = retrieveconfig(conn, collection, masarconf, withpvs=True) self.assertEqual("inactive", res3[0]['status']) ui.updatemasarconfigstatus("active", 1) res3 = retrieveconfig(conn, collection, masarconf, withpvs=True) self.assertEqual("active", res3[0]['status'])
def testRetrieveSnapshot(self): name = 'SR-All-20140326' test_comment = "test" test_approval = True test_username = "******" test_masar_data = [0] params = {"desc": "SR daily SCR setpoint: SR and IS PS, RF", "system": "SR", "status": "inactive", "version": 20140326, } newid = saveconfig(self.conn, self.collection, name, **params) new = retrieveconfig(self.conn, self.collection, name=name) self.assertEqual(len(new), 1, "Should find only one entry instead of %s" % len(new)) configidx = new[0]["configidx"] eventid = saveevent(self.conn, self.collection, configidx=configidx, comment=test_comment, approval=test_approval, masar_data=test_masar_data, username=test_username) self.assertNotEqual(eventid, None) result = retrievesnapshot(self.conn, self.collection, eventidx=eventid) self.assertEqual(result["eventidx"], eventid) self.assertEqual(result["configidx"], configidx) self.assertEqual(result["comment"], test_comment) self.assertEqual(result["approval"], test_approval) self.assertEqual(result["username"], test_username) self.assertEqual(result["masar_data"], test_masar_data)
def retrieveServiceConfigs(self, params): """Retrieve configurations :param params: a dictionary to carry query condition with structure like: :: {"configname": [optional], # configuration name, wildcast allowed with * for multiple characters matching "system": [optional], # system name, wildcast allowed with * for multiple characters matching "configversion": [optional], # configuration version number "status": [optional], # either active or inactive, otherwise reset to None } or {'eventid': , # event index number to get which configuration this event belongs to} :returns: list with tuple with header description for each field. Structure like: :: [('config_idx', 'config_name', 'config_desc', 'config_create_date', 'config_version', 'status'), ...] :raises: """ key = ['configname', 'configversion', 'system', 'status', 'eventid'] configname, version, system, status, eventid = self._parseParams(params, key) if isinstance(eventid, (str, unicode)): eventid = int(eventid) if status is not None: status = status.lower() if status not in ["active", "inactive"]: status = None if system is not None and system.lower() == "all": system = None mongoconn, collection = utils.conn(host=os.environ["MASAR_MONGO_HOST"], port=os.environ["MASAR_MONGO_PORT"], db=os.environ["MASAR_MONGO_DB"]) if eventid is not None: result = pymasar.retrieveconfig(mongoconn, collection, eventidx=eventid) elif system is None and configname is None: result = pymasar.retrieveconfig(mongoconn, collection, status=status) elif system is None: result = pymasar.retrieveconfig(mongoconn, collection, name=configname, status=status) else: result = pymasar.retrieveconfig(mongoconn, collection, system=system, status=status) utils.close(mongoconn) results = [('config_idx', 'config_name', 'config_desc', 'config_create_date', 'config_version', 'status')] for res in result: results.append((res["configidx"], res["name"], res["desc"], res["created_on"], res["version"], res["status"])) return results
def testSaveEvents(self): name = 'SR-All-20140326' params = { "desc": "SR daily SCR setpoint: SR and IS PS, RF", "system": "SR", "status": "inactive", "version": 20140326, } newid = saveconfig(self.conn, self.collection, name, **params) new = retrieveconfig(self.conn, self.collection, name=name) self.assertEqual(len(new), 1, "Should find only one entry instead of %s" % len(new)) configidx = new[0]["configidx"] with self.assertRaises(RuntimeError) as context: eventid = saveevent(self.conn, self.collection, configidx=configidx, comment="good snapshot", approval=True, masar_data=None, username="******") self.assertEqual(context.exception.message, "Data set can not be empty.") with self.assertRaises(RuntimeError) as context: eventid = saveevent(self.conn, self.collection, configidx=None, comment="good snapshot", approval=True, masar_data=["element"], username="******") self.assertEqual(context.exception.message, "Cannot identify configuration index number.") with self.assertRaises(ValueError) as context: eventid = saveevent(self.conn, self.collection, configidx=-1, comment="good snapshot", approval=True, masar_data=["element"], username="******") self.assertEqual(context.exception.message, "Unknown configuration index number (%s)" % str(-1)) eventid = saveevent(self.conn, self.collection, configidx=configidx, comment="good snapshot", approval=True, masar_data=["element"], username="******") self.assertNotEqual(eventid, None)
def testSaveEvents(self): name = 'SR-All-20140326' params = {"desc": "SR daily SCR setpoint: SR and IS PS, RF", "system": "SR", "status": "inactive", "version": 20140326, } newid = saveconfig(self.conn, self.collection, name, **params) new = retrieveconfig(self.conn, self.collection, name=name) self.assertEqual(len(new), 1, "Should find only one entry instead of %s"%len(new)) configidx = new[0]["configidx"] with self.assertRaises(RuntimeError) as context: eventid = saveevent(self.conn, self.collection, configidx=configidx, comment="good snapshot", approval=True, masar_data=None, username="******") self.assertEqual(context.exception.message, "Data set can not be empty.") with self.assertRaises(RuntimeError) as context: eventid = saveevent(self.conn, self.collection, configidx=None, comment="good snapshot", approval=True, masar_data=["element"], username="******") self.assertEqual(context.exception.message, "Cannot identify configuration index number.") with self.assertRaises(ValueError) as context: eventid = saveevent(self.conn, self.collection, configidx=-1, comment="good snapshot", approval=True, masar_data=["element"], username="******") self.assertEqual(context.exception.message, "Unknown configuration index number (%s)" % str(-1)) eventid = saveevent(self.conn, self.collection, configidx=configidx, comment="good snapshot", approval=True, masar_data=["element"], username="******") self.assertNotEqual(eventid, None)
def retrieveSystems(self, params): """Retrieve system list :param params: a dictionary to carry query condition with structure like: :: {"system": [optional], # system name, wildcast allowed with * for multiple characters matching "configname": [optional], # configuration name, wildcast allowed with * for multiple characters matching } :returns: list with tuple with header description for each field. Structure like: :: [('config_id', 'config_idx', 'system_key', 'system_val'), ...] :raises: """ key = ['system', 'configname'] system, configname = self._parseParams(params, key) mongoconn, collection = utils.conn(host=os.environ["MASAR_MONGO_HOST"], port=os.environ["MASAR_MONGO_PORT"], db=os.environ["MASAR_MONGO_DB"]) if system is None and configname is None: result = pymasar.retrieveconfig(mongoconn, collection) elif system is None: result = pymasar.retrieveconfig(mongoconn, collection, name=configname) else: if system.lower() == "all": result = pymasar.retrieveconfig(mongoconn, collection) else: result = pymasar.retrieveconfig(mongoconn, collection, system=system) utils.close(mongoconn) results = [('config_prop_id', 'config_idx', 'system_key', 'system_val')] for res in result: results.append((int(str(res["_id"]), 16), res["configidx"], "system", res["system"])) return results
def testSaveMasarMongoDB(self): app = QtGui.QApplication(sys.argv) ui = dbmanagerUI() ui.dbsource = 1 # Called normally with menu selection ui.defaultmongodb() ui.test_in_progress_flag = 1 ui.savemasarmongodb() masarconf = 'newcfgname' conn, collection = utils.conn(host=masarconfig.get('mongodb', 'host'), port=masarconfig.get('mongodb', 'port'), db=masarconfig.get('mongodb', 'database')) res3 = retrieveconfig(conn, collection, masarconf, withpvs=True) self.assertEqual('newcfgname', res3[0]['name']) self.assertEqual('newmsystem', res3[0]['system']) self.assertEqual('newcfgdesc', res3[0]['desc'])
def testSaveMasarMongoDB(self): app = QtGui.QApplication(sys.argv) ui = dbmanagerUI() ui.dbsource = 1 # Called normally with menu selection ui.defaultmongodb() ui.test_in_progress_flag = 1 ui.savemasarmongodb() masarconf = 'newcfgname' conn, collection = utils.conn(host=masarconfig.get('mongodb', 'host'), port=masarconfig.get('mongodb', 'port'), db=masarconfig.get( 'mongodb', 'database')) res3 = retrieveconfig(conn, collection, masarconf, withpvs=True) self.assertEqual('newcfgname', res3[0]['name']) self.assertEqual('newmsystem', res3[0]['system']) self.assertEqual('newcfgdesc', res3[0]['desc'])
def testUpdateEvents(self): name = 'SR-All-20140326' test_comment = "test" updated_comment = "updated" test_approval = True updated_approval = False test_username = "******" updated_username = "******" test_masar_data = [0] params = { "desc": "SR daily SCR setpoint: SR and IS PS, RF", "system": "SR", "status": "inactive", "version": 20140326, } newid = saveconfig(self.conn, self.collection, name, **params) new = retrieveconfig(self.conn, self.collection, name=name) self.assertEqual(len(new), 1, "Should find only one entry instead of %s" % len(new)) configidx = new[0]["configidx"] eventid = saveevent(self.conn, self.collection, configidx=configidx, comment=test_comment, approval=test_approval, masar_data=test_masar_data, username=test_username) self.assertNotEqual(eventid, None) with self.assertRaises(RuntimeError) as context: result = updateevent(self.conn, self.collection, configidx=None, comment=updated_comment, approval=updated_approval, username=updated_username) self.assertEqual(context.exception.message, "Unknown MASAR event to update.") with self.assertRaises(RuntimeError) as context: result = updateevent(self.conn, self.collection, eventidx=eventid) self.assertEqual(context.exception.message, "No fields to update.") result = updateevent(self.conn, self.collection, eventidx=eventid, comment=updated_comment, approval=updated_approval, username=updated_username) self.assertTrue(result)
def testUpdateEvents(self): name = 'SR-All-20140326' test_comment = "test" updated_comment = "updated" test_approval = True updated_approval = False test_username = "******" updated_username = "******" test_masar_data = [0] params = {"desc": "SR daily SCR setpoint: SR and IS PS, RF", "system": "SR", "status": "inactive", "version": 20140326, } newid = saveconfig(self.conn, self.collection, name, **params) new = retrieveconfig(self.conn, self.collection, name=name) self.assertEqual(len(new), 1, "Should find only one entry instead of %s" % len(new)) configidx = new[0]["configidx"] eventid = saveevent(self.conn, self.collection, configidx=configidx, comment=test_comment, approval=test_approval, masar_data=test_masar_data, username=test_username) self.assertNotEqual(eventid, None) with self.assertRaises(RuntimeError) as context: result = updateevent(self.conn, self.collection, configidx=None, comment=updated_comment, approval=updated_approval, username=updated_username) self.assertEqual(context.exception.message, "Unknown MASAR event to update.") with self.assertRaises(RuntimeError) as context: result = updateevent(self.conn, self.collection, eventidx=eventid) self.assertEqual(context.exception.message, "No fields to update.") result = updateevent(self.conn, self.collection, eventidx=eventid, comment=updated_comment, approval=updated_approval, username=updated_username) self.assertTrue(result)
def testSaveMongoServiceConfigs(self): conn, collection = utils.conn(host=masarconfig.get('mongodb', 'host'), port=masarconfig.get('mongodb', 'port'), db=masarconfig.get('mongodb', 'database')) conn.drop_database(masarconfig.get('mongodb', 'database')) saveMongoService(self.parsed_json) res3 = retrieveconfig(conn, collection, 'BR_MG_SCR_20130419', withpvs=True) self.assertEqual(res3[0]['status'], 'active') self.assertEqual('BR_MG_SCR_20130419', res3[0]['name']) self.assertEqual(res3[0]['pvlist']['names'], [u'masarExample0000', u'masarExample0001', u'masarExampleBoUninit', u'masarExampleMbboUninit', u'masarExample0002', u'masarExample0003', u'masarExample0004', u'masarExampleCharArray', u'masarExampleShortArray', u'masarExampleLongArray', u'masarExampleStringArray', u'masarExampleFloatArray', u'masarExampleDoubleArray', u'masarExampleMbboUninitTest']) self.assertEqual('BR', res3[0]['system']) self.assertEqual(3, len(res3[0]['created_on'].split('-'))) # Date format test self.assertEqual(3, len(res3[0]['created_on'].split(':'))) # 2016-07-28 18:18:36 self.assertEqual(None, res3[0]['version']) self.assertEqual(3, len(res3[0]['updated_on'].split('-'))) # Date format test self.assertEqual(3, len(res3[0]['updated_on'].split(':'))) # 2016-07-28 18:18:36 self.assertNotEqual(None, res3[0]['_id']) self.assertEqual('BR ramping PS daily SCR setpoint', res3[0]['desc'])
def retrieveSnapshot(self, params): """Retrieve snapshot data :param params: a dictionary to carry query condition with structure like: :: {"eventid": , # event index number} :returns: 2-d list with tuple with header description for each field. Structure like: :: [[('user tag', 'event time', 'service config name', 'service name'), ('pv name', 'string value', 'double value', 'long value', 'dbr type', 'isConnected', 'secondsPastEpoch', 'nanoSeconds', 'timeStampTag', 'alarmSeverity', 'alarmStatus', 'alarmMessage', 'is_array', 'array_value')], # header information to determine returning data [(comment, date, config name, None), (value for pv1 as described above), (value for pv2), ...] :raises: """ key = ['eventid', 'comment'] eid, _ = self._parseParams(params, key) result = [[('user tag', 'event time', 'service config name', 'service name'), ('pv name', 'string value', 'double value', 'long value', 'dbr type', 'isConnected', 'secondsPastEpoch', 'nanoSeconds', 'timeStampTag', 'alarmSeverity', 'alarmStatus', 'alarmMessage', 'is_array', 'array_value')]] if eid is not None: if isinstance(eid, (str, unicode)): eid = int(eid) mongoconn, collection = utils.conn(host=os.environ["MASAR_MONGO_HOST"], port=os.environ["MASAR_MONGO_PORT"], db=os.environ["MASAR_MONGO_DB"]) eiddata = pymasar.retrievesnapshot(mongoconn, collection, eid) configname = pymasar.retrieveconfig(mongoconn, collection, configidx=eiddata["configidx"])[0]["name"] utils.close(mongoconn) temp = [(eiddata["comment"], eiddata["created_on"], configname, None), ] for d in eiddata["masar_data"]: temp.append(tuple(d)) result.append(temp) return result
def saveSnapshot(self, params): """Save event with data. :param params: a dictionary to carry query condition with structure like: :: [[(channel name,), (string value,),(double value,),(long value,),(dbr type),(is connected), (second past epoch,),(nano seconds,),(time stamp tag,), (alarm severity,),(alarm status,),(alarm message,), (is_array), (array_value) ], {"configname": , # configuration name which the new data set belongs to "comment": [optional], # comment description for this new data set "approval": [optional], # approval status, False is not provided "username": [optional], # user name who commands this action } ] :returns: list with tuple with header description for each field. Structure like: :: [event_id] or [-1] if fault :raises: ValueError """ key = ['configname', 'comment', 'approval', 'username'] config, comment, approval, username = self._parseParams(params[1], key) if config is None: raise ValueError("Unknown configuration when saving a new snapshot event.") if approval is None: approval = False else: approval = bool(json.loads(str(approval).lower())) result = NTMultiChannel(params[0]) dataLen = result.getNumberChannel() if dataLen == 0: raise RuntimeError("No available snapshot data.") # values format: the value is raw data from IOC # [(channel name,), (value,), (dbr type), (is connected), # (second past epoch,), (nano seconds,), (time stamp tag,), # (alarm severity,), (alarm status,), (alarm message,)] pvnames = result.getChannelName() values = result.getValue() dbrtype = result.getDbrType() isconnected = result.getIsConnected() severity = result.getSeverity() status = result.getStatus() message = result.getMessage() sec = result.getSecondsPastEpoch() nanosec = result.getNanoseconds() usertag = result.getUserTag() # data format: the data is prepared to save into rdb # rawdata format # [('channel name', 'string value', 'double value', 'long value', 'dbr type', 'is connected', # 'seconds past epoch', 'nano seconds', 'time stamp tag', 'alarm severity', 'alarm status', # 'alarm message', 'is_array', 'array_value'), # ... # ] datas = [] # get IOC raw data for i in range(dataLen): tmp = [] if isinstance(values[i], (list, tuple)): tmp = [pvnames[i], "", None, None, dbrtype[i], isconnected[i], sec[i], nanosec[i], usertag[i], severity[i], status[i], message[i], 1, values[i]] else: if dbrtype[i] in self.epicsString: tmp = [pvnames[i], values[i], None, None, dbrtype[i], isconnected[i], sec[i], nanosec[i], usertag[i], severity[i], status[i], message[i], 0, None] else: tmp = [pvnames[i], str(values[i]), values[i], values[i], dbrtype[i], isconnected[i], sec[i], nanosec[i], usertag[i], severity[i], status[i], message[i], 0, None] datas.append(tmp) # save into database try: mongoconn, collection = utils.conn(host=os.environ["MASAR_MONGO_HOST"], port=os.environ["MASAR_MONGO_PORT"], db=os.environ["MASAR_MONGO_DB"]) configs = pymasar.retrieveconfig(mongoconn, collection, name=config) if len(configs) != 1: raise RuntimeError("Cannot find a unique configuration.") eid = pymasar.saveevent(mongoconn, collection, configidx=configs[0]["configidx"], comment=comment, approval=approval, username=username, masar_data=datas) utils.close(mongoconn) return [eid, ] except: # keep the same format with a normal operation return [-1]
def testSaveconfig(self): name = "SR_All_20140421" params = { "desc": "SR daily SCR setpoint without IS kick and septum: SR and RF", "system": "SR", "status": "active", "version": 20140421, } newid = saveconfig(self.conn, self.collection, name, **params) new = retrieveconfig(self.conn, self.collection, name=name) self.assertEqual(len(new), 1, "Should find only one entry instead of %s" % len(new)) self.assertEqual(newid, new[0]["_id"], "Expecting id %s but got %s" % (newid, new[0]["_id"])) with self.assertRaises(ValueError) as context: saveconfig(self.conn, self.collection, name, **params) self.assertEqual(context.exception.message, "Configuration (%s) exists already." % name) name1 = 'SR-All-20140326' params1 = { "desc": "SR daily SCR setpoint: SR and IS PS, RF", "system": "SR", "status": "inactive", "version": 20140326, } newid1 = saveconfig(self.conn, self.collection, name1, **params1) new1 = retrieveconfig(self.conn, self.collection, name=name1) self.assertEqual( len(new1), 1, "Should find only one entry instead of %s" % len(new1)) self.assertEqual( newid1, new1[0]["_id"], "Expecting id %s but got %s" % (newid1, new1[0]["_id"])) self.assertEqual(new1[0]["configidx"] - new[0]["configidx"], 1) name2 = 'SR-All-LTB_PS_"SRC_20131206' params2 = { "desc": "LTB power supply setpoints, for saving/comparing/restoring", "system": "LTB", "status": "active", "version": 20131206, } newid2 = saveconfig(self.conn, self.collection, name2, **params2) new2 = retrieveconfig(self.conn, self.collection, name=name2) self.assertEqual( len(new2), 1, "Should find only one entry instead of %s" % len(new2)) self.assertEqual( newid2, new2[0]["_id"], "Expecting id %s but got %s" % (newid2, new2[0]["_id"])) self.assertEqual(new2[0]["configidx"] - new1[0]["configidx"], 1) name3 = 'LTB_BR_BTS_20140421' params3 = { "desc": "BR SCR PVs with IS kick and septum: LTB, BT, BTS, SR IS", "system": "LTB, BR, BTS", "status": "active", "version": 20140421, } newid3 = saveconfig(self.conn, self.collection, name3, **params3) new3 = retrieveconfig(self.conn, self.collection, name=name3) self.assertEqual( len(new3), 1, "Should find only one entry instead of %s" % len(new3)) self.assertEqual( newid3, new3[0]["_id"], "Expecting id %s but got %s" % (newid3, new3[0]["_id"])) self.assertEqual(new3[0]["configidx"] - new2[0]["configidx"], 1) system4SR = retrieveconfig(self.conn, self.collection, system="SR") self.assertEqual(len(system4SR), 2) system4more = retrieveconfig(self.conn, self.collection, system=params3["system"]) self.assertEqual(len(system4more), 1) system4all = retrieveconfig(self.conn, self.collection, system="*") self.assertEqual(len(system4all), 4) system4all = retrieveconfig(self.conn, self.collection, system="LTB*") self.assertEqual(len(system4all), 2) system4all = retrieveconfig(self.conn, self.collection, system="L*B*") self.assertEqual(len(system4all), 2) system4all = retrieveconfig(self.conn, self.collection, system="L*B,*") self.assertEqual(len(system4all), 1) system4all = retrieveconfig(self.conn, self.collection, system="*S*B,*") self.assertEqual(len(system4all), 0)
def testUpdateconfig(self): """""" name = "SR_All_20140421" params = { "desc": "SR daily SCR setpoint without IS kick and septum: SR and RF", "system": "SR", "status": "active", "version": 20140421, } with self.assertRaises(RuntimeError) as context: updateconfig(self.conn, self.collection, None) self.assertEqual(context.exception.message, "Cannot identify configuration to update.") time.sleep(1) with self.assertRaises(RuntimeError) as context: updateconfig(self.conn, self.collection, name) self.assertEqual(context.exception.message, "Wrong Mongo document for %s" % name) newid = saveconfig(self.conn, self.collection, name, **params) res0 = retrieveconfig(self.conn, self.collection, name) self.assertTrue( updateconfig(self.conn, self.collection, name, status="inactive")) res1 = retrieveconfig(self.conn, self.collection, name) self.assertEqual(newid, res0[0]["_id"]) self.assertEqual(newid, res1[0]["_id"]) self.assertEqual(res0[0]["status"], "active") self.assertEqual(res1[0]["status"], "inactive") self.assertEqual(res1[0]["created_on"], res0[0]["created_on"]) time.sleep(1) # delay required for below updated_on inequality test self.assertTrue( updateconfig(self.conn, self.collection, name, status="active")) res2 = retrieveconfig(self.conn, self.collection, name) self.assertEqual(res2[0]["status"], "active") self.assertNotEqual(res1[0]["updated_on"], res2[0]["updated_on"]) self.assertEqual(res1[0]["created_on"], res2[0]["created_on"]) self.assertEqual(res1[0]["created_on"], res0[0]["created_on"]) pvs = [ "RF{Osc:1}Freq:I", "SR-RF{CFC:D}E:Fb-SP", "SR-RF{CFC:D}Phs:Fb-SP", "SR-RF{CFC:D}Tuner:PhaOff-SP", "SR:C01-MG{PS:BT1A}I:Sp1-SP", "SR:C01-MG{PS:BT1A}I:Sp2-SP", "SR:C01-MG{PS:CH1B}I:Sp1-SP", "SR:C01-MG{PS:CH1B}I:Sp2-SP", "SR:C01-MG{PS:CH2B}I:Sp1-SP", "SR:C01-MG{PS:CH2B}I:Sp2-SP", "SR:C01-MG{PS:CL1A}I:Sp1-SP", "SR:C01-MG{PS:CL1A}I:Sp2-SP", "SR:C01-MG{PS:CL2A}I:Sp1-SP", "SR:C01-MG{PS:CL2A}I:Sp2-SP", "SR:C01-MG{PS:CM1A}I:Sp1-SP", "SR:C01-MG{PS:CM1A}I:Sp2-SP", "SR:C01-MG{PS:CM1B}I:Sp1-SP", "SR:C01-MG{PS:CM1B}I:Sp2-SP", "SR:C01-MG{PS:QH1B}I:Sp1-SP", "SR:C01-MG{PS:QH2B}I:Sp1-SP", "SR:C01-MG{PS:QH3B}I:Sp1-SP", "SR:C01-MG{PS:QL1A}I:Sp1-SP", "SR:C01-MG{PS:QL2A}I:Sp1-SP", "SR:C01-MG{PS:QL3A}I:Sp1-SP", "SR:C01-MG{PS:QM1A}I:Sp1-SP", "SR:C01-MG{PS:QM1B}I:Sp1-SP", "SR:C01-MG{PS:QM2A}I:Sp1-SP", "SR:C01-MG{PS:QM2B}I:Sp1-SP", "SR:C01-MG{PS:SH4-P2}I:Sp1-SP", "SR:C01-MG{PS:SM1A-P2}I:Sp1-SP", "SR:C01-MG{PS:SQKM1A}I:Sp1-SP", "SR:C02-MG{PS:BT1A}I:Sp1-SP", "SR:C02-MG{PS:BT1A}I:Sp2-SP", "SR:C02-MG{PS:CH1A}I:Sp1-SP", "SR:C02-MG{PS:CH1A}I:Sp2-SP", "SR:C02-MG{PS:CH2A}I:Sp1-SP", "SR:C02-MG{PS:CH2A}I:Sp2-SP", "SR:C02-MG{PS:CL1B}I:Sp1-SP", "SR:C02-MG{PS:CL1B}I:Sp2-SP", "SR:C02-MG{PS:CL2B}I:Sp1-SP", "SR:C02-MG{PS:CL2B}I:Sp2-SP", "SR:C02-MG{PS:CM1A}I:Sp1-SP", "SR:C02-MG{PS:CM1A}I:Sp2-SP", "SR:C02-MG{PS:CM1B}I:Sp1-SP", "SR:C02-MG{PS:CM1B}I:Sp2-SP", "SR:C02-MG{PS:QH1A}I:Sp1-SP", "SR:C02-MG{PS:QH2A}I:Sp1-SP", "SR:C02-MG{PS:QH3A}I:Sp1-SP", "SR:C02-MG{PS:QL1B}I:Sp1-SP", "SR:C02-MG{PS:QL2B}I:Sp1-SP", "SR:C02-MG{PS:QL3B}I:Sp1-SP", "SR:C02-MG{PS:QM1A}I:Sp1-SP", "SR:C02-MG{PS:QM1B}I:Sp1-SP", "SR:C02-MG{PS:QM2A}I:Sp1-SP", "SR:C02-MG{PS:QM2B}I:Sp1-SP", "SR:C02-MG{PS:SM1B-P2}I:Sp1-SP", "SR:C02-MG{PS:SM2B-P2}I:Sp1-SP", "SR:C02-MG{PS:SQKH1A}I:Sp1-SP", "SR:C03-MG{PS:BT1A}I:Sp1-SP", "SR:C03-MG{PS:BT1A}I:Sp2-SP", "SR:C03-MG{PS:CH1B}I:Sp1-SP", "SR:C03-MG{PS:CH1B}I:Sp2-SP", "SR:C03-MG{PS:CH2B}I:Sp1-SP", "SR:C03-MG{PS:CH2B}I:Sp2-SP", "SR:C03-MG{PS:CL1A}I:Sp1-SP", "SR:C03-MG{PS:CL1A}I:Sp2-SP", "SR:C03-MG{PS:CL2A}I:Sp1-SP", "SR:C03-MG{PS:CL2A}I:Sp2-SP", "SR:C03-MG{PS:CM1A}I:Sp1-SP", "SR:C03-MG{PS:CM1A}I:Sp2-SP", "SR:C03-MG{PS:CM1B}I:Sp1-SP", "SR:C03-MG{PS:CM1B}I:Sp2-SP", "SR:C03-MG{PS:D-SP}I:Sp1-SP", "SR:C03-MG{PS:QH1B}I:Sp1-SP", "SR:C03-MG{PS:QH2B}I:Sp1-SP", "SR:C03-MG{PS:QH3B}I:Sp1-SP", "SR:C03-MG{PS:QL1A}I:Sp1-SP", "SR:C03-MG{PS:QL2A}I:Sp1-SP", "SR:C03-MG{PS:QL3A}I:Sp1-SP", "SR:C03-MG{PS:QM1A}I:Sp1-SP", "SR:C03-MG{PS:QM1B}I:Sp1-SP", "SR:C03-MG{PS:QM2A}I:Sp1-SP", "SR:C03-MG{PS:QM2B}I:Sp1-SP", "SR:C03-MG{PS:SL2-P2}I:Sp1-SP", "SR:C03-MG{PS:SL3-P2}I:Sp1-SP", "SR:C03-MG{PS:SQKM1A}I:Sp1-SP", "SR:C04-MG{PS:BT1A}I:Sp1-SP", "SR:C04-MG{PS:BT1A}I:Sp2-SP", "SR:C04-MG{PS:CH1A}I:Sp1-SP", "SR:C04-MG{PS:CH1A}I:Sp2-SP", "SR:C04-MG{PS:CH2A}I:Sp1-SP", "SR:C04-MG{PS:CH2A}I:Sp2-SP", "SR:C04-MG{PS:CL1B}I:Sp1-SP", "SR:C04-MG{PS:CL1B}I:Sp2-SP", "SR:C04-MG{PS:CL2B}I:Sp1-SP", "SR:C04-MG{PS:CL2B}I:Sp2-SP", "SR:C04-MG{PS:CM1A}I:Sp1-SP", "SR:C04-MG{PS:CM1A}I:Sp2-SP", "SR:C04-MG{PS:CM1B}I:Sp1-SP", "SR:C04-MG{PS:CM1B}I:Sp2-SP", "SR:C04-MG{PS:QH1A}I:Sp1-SP", "SR:C04-MG{PS:QH2A}I:Sp1-SP", "SR:C04-MG{PS:QH3A}I:Sp1-SP", "SR:C04-MG{PS:QL1B}I:Sp1-SP", "SR:C04-MG{PS:QL2B}I:Sp1-SP", "SR:C04-MG{PS:QL3B}I:Sp1-SP", "SR:C04-MG{PS:QM1A}I:Sp1-SP", "SR:C04-MG{PS:QM1B}I:Sp1-SP", "SR:C04-MG{PS:QM2A}I:Sp1-SP", "SR:C04-MG{PS:QM2B}I:Sp1-SP", "SR:C04-MG{PS:SL1-P2}I:Sp1-SP", "SR:C04-MG{PS:SQKH1A}I:Sp1-SP", "SR:C05-MG{PS:BT1A}I:Sp1-SP", "SR:C05-MG{PS:BT1A}I:Sp2-SP", "SR:C05-MG{PS:CH1B}I:Sp1-SP", "SR:C05-MG{PS:CH1B}I:Sp2-SP", "SR:C05-MG{PS:CH2B}I:Sp1-SP", "SR:C05-MG{PS:CH2B}I:Sp2-SP", "SR:C05-MG{PS:CL1A}I:Sp1-SP", "SR:C05-MG{PS:CL1A}I:Sp2-SP", "SR:C05-MG{PS:CL2A}I:Sp1-SP", "SR:C05-MG{PS:CL2A}I:Sp2-SP", "SR:C05-MG{PS:CM1A}I:Sp1-SP", "SR:C05-MG{PS:CM1A}I:Sp2-SP", "SR:C05-MG{PS:CM1B}I:Sp1-SP", "SR:C05-MG{PS:CM1B}I:Sp2-SP", "SR:C05-MG{PS:QH1B}I:Sp1-SP", "SR:C05-MG{PS:QH2B}I:Sp1-SP", "SR:C05-MG{PS:QH3B}I:Sp1-SP", "SR:C05-MG{PS:QL1A}I:Sp1-SP", "SR:C05-MG{PS:QL2A}I:Sp1-SP", "SR:C05-MG{PS:QL3A}I:Sp1-SP", "SR:C05-MG{PS:QM1A}I:Sp1-SP", "SR:C05-MG{PS:QM1B}I:Sp1-SP", "SR:C05-MG{PS:QM2A}I:Sp1-SP", "SR:C05-MG{PS:QM2B}I:Sp1-SP", "SR:C05-MG{PS:SQKM1A}I:Sp1-SP", "SR:C06-MG{PS:BT1A}I:Sp1-SP", "SR:C06-MG{PS:BT1A}I:Sp2-SP", "SR:C06-MG{PS:CH1A}I:Sp1-SP", "SR:C06-MG{PS:CH1A}I:Sp2-SP", "SR:C06-MG{PS:CH2A}I:Sp1-SP", "SR:C06-MG{PS:CH2A}I:Sp2-SP", "SR:C06-MG{PS:CL1B}I:Sp1-SP", "SR:C06-MG{PS:CL1B}I:Sp2-SP", "SR:C06-MG{PS:CL2B}I:Sp1-SP", "SR:C06-MG{PS:CL2B}I:Sp2-SP", "SR:C06-MG{PS:CM1A}I:Sp1-SP", "SR:C06-MG{PS:CM1A}I:Sp2-SP", "SR:C06-MG{PS:CM1B}I:Sp1-SP", "SR:C06-MG{PS:CM1B}I:Sp2-SP", "SR:C06-MG{PS:QH1A}I:Sp1-SP", "SR:C06-MG{PS:QH2A}I:Sp1-SP", "SR:C06-MG{PS:QH3A}I:Sp1-SP", "SR:C06-MG{PS:QL1B}I:Sp1-SP", "SR:C06-MG{PS:QL2B}I:Sp1-SP", "SR:C06-MG{PS:QL3B}I:Sp1-SP", "SR:C06-MG{PS:QM1A}I:Sp1-SP", "SR:C06-MG{PS:QM1B}I:Sp1-SP", "SR:C06-MG{PS:QM2A}I:Sp1-SP", "SR:C06-MG{PS:QM2B}I:Sp1-SP", "SR:C06-MG{PS:SH1-P3}I:Sp1-SP", "SR:C06-MG{PS:SH3-P3}I:Sp1-SP", "SR:C06-MG{PS:SQKH1A}I:Sp1-SP", "SR:C07-MG{PS:BT1A}I:Sp1-SP", "SR:C07-MG{PS:BT1A}I:Sp2-SP", "SR:C07-MG{PS:CH1B}I:Sp1-SP", "SR:C07-MG{PS:CH1B}I:Sp2-SP", "SR:C07-MG{PS:CH2B}I:Sp1-SP", "SR:C07-MG{PS:CH2B}I:Sp2-SP", "SR:C07-MG{PS:CL1A}I:Sp1-SP", "SR:C07-MG{PS:CL1A}I:Sp2-SP", "SR:C07-MG{PS:CL2A}I:Sp1-SP", "SR:C07-MG{PS:CL2A}I:Sp2-SP", "SR:C07-MG{PS:CM1A}I:Sp1-SP", "SR:C07-MG{PS:CM1A}I:Sp2-SP", "SR:C07-MG{PS:CM1B}I:Sp1-SP", "SR:C07-MG{PS:CM1B}I:Sp2-SP", "SR:C07-MG{PS:QH1B}I:Sp1-SP", "SR:C07-MG{PS:QH2B}I:Sp1-SP", "SR:C07-MG{PS:QH3B}I:Sp1-SP", "SR:C07-MG{PS:QL1A}I:Sp1-SP", "SR:C07-MG{PS:QL2A}I:Sp1-SP", "SR:C07-MG{PS:QL3A}I:Sp1-SP", "SR:C07-MG{PS:QM1A}I:Sp1-SP", "SR:C07-MG{PS:QM1B}I:Sp1-SP", "SR:C07-MG{PS:QM2A}I:Sp1-SP", "SR:C07-MG{PS:QM2B}I:Sp1-SP", "SR:C07-MG{PS:SH4-P3}I:Sp1-SP", "SR:C07-MG{PS:SM1A-P3}I:Sp1-SP", "SR:C07-MG{PS:SQKM1A}I:Sp1-SP", "SR:C08-MG{PS:BT1A}I:Sp1-SP", "SR:C08-MG{PS:BT1A}I:Sp2-SP", "SR:C08-MG{PS:CH1A}I:Sp1-SP", "SR:C08-MG{PS:CH1A}I:Sp2-SP", "SR:C08-MG{PS:CH2A}I:Sp1-SP", "SR:C08-MG{PS:CH2A}I:Sp2-SP", "SR:C08-MG{PS:CL1B}I:Sp1-SP", "SR:C08-MG{PS:CL1B}I:Sp2-SP", "SR:C08-MG{PS:CL2B}I:Sp1-SP", "SR:C08-MG{PS:CL2B}I:Sp2-SP", "SR:C08-MG{PS:CM1A}I:Sp1-SP", "SR:C08-MG{PS:CM1A}I:Sp2-SP", "SR:C08-MG{PS:CM1B}I:Sp1-SP", "SR:C08-MG{PS:CM1B}I:Sp2-SP", "SR:C08-MG{PS:QH1A}I:Sp1-SP", "SR:C08-MG{PS:QH2A}I:Sp1-SP", "SR:C08-MG{PS:QH3A}I:Sp1-SP", "SR:C08-MG{PS:QL1B}I:Sp1-SP", "SR:C08-MG{PS:QL2B}I:Sp1-SP", "SR:C08-MG{PS:QL3B}I:Sp1-SP", "SR:C08-MG{PS:QM1A}I:Sp1-SP", "SR:C08-MG{PS:QM1B}I:Sp1-SP", "SR:C08-MG{PS:QM2A}I:Sp1-SP", "SR:C08-MG{PS:QM2B}I:Sp1-SP", "SR:C08-MG{PS:SH1-DW08}I:Sp1-SP", "SR:C08-MG{PS:SH3-DW08}I:Sp1-SP", "SR:C08-MG{PS:SH4-DW08}I:Sp1-SP", "SR:C08-MG{PS:SM1B-P3}I:Sp1-SP", "SR:C08-MG{PS:SM2B-P3}I:Sp1-SP", "SR:C08-MG{PS:SQKH1A}I:Sp1-SP", "SR:C09-MG{PS:BT1A}I:Sp1-SP", "SR:C09-MG{PS:BT1A}I:Sp2-SP", "SR:C09-MG{PS:CH1B}I:Sp1-SP", "SR:C09-MG{PS:CH1B}I:Sp2-SP", "SR:C09-MG{PS:CH2B}I:Sp1-SP", "SR:C09-MG{PS:CH2B}I:Sp2-SP", "SR:C09-MG{PS:CL1A}I:Sp1-SP", "SR:C09-MG{PS:CL1A}I:Sp2-SP", "SR:C09-MG{PS:CL2A}I:Sp1-SP", "SR:C09-MG{PS:CL2A}I:Sp2-SP", "SR:C09-MG{PS:CM1A}I:Sp1-SP", "SR:C09-MG{PS:CM1A}I:Sp2-SP", "SR:C09-MG{PS:CM1B}I:Sp1-SP", "SR:C09-MG{PS:CM1B}I:Sp2-SP", "SR:C09-MG{PS:QH1B}I:Sp1-SP", "SR:C09-MG{PS:QH2B}I:Sp1-SP", "SR:C09-MG{PS:QH3B}I:Sp1-SP", "SR:C09-MG{PS:QL1A}I:Sp1-SP", "SR:C09-MG{PS:QL2A}I:Sp1-SP", "SR:C09-MG{PS:QL3A}I:Sp1-SP", "SR:C09-MG{PS:QM1A}I:Sp1-SP", "SR:C09-MG{PS:QM1B}I:Sp1-SP", "SR:C09-MG{PS:QM2A}I:Sp1-SP", "SR:C09-MG{PS:QM2B}I:Sp1-SP", "SR:C09-MG{PS:SL2-P3}I:Sp1-SP", "SR:C09-MG{PS:SL3-P3}I:Sp1-SP", "SR:C09-MG{PS:SQKM1A}I:Sp1-SP", "SR:C10-MG{PS:BT1A}I:Sp1-SP", "SR:C10-MG{PS:BT1A}I:Sp2-SP", "SR:C10-MG{PS:CH1A}I:Sp1-SP", "SR:C10-MG{PS:CH1A}I:Sp2-SP", "SR:C10-MG{PS:CH2A}I:Sp1-SP", "SR:C10-MG{PS:CH2A}I:Sp2-SP", "SR:C10-MG{PS:CL1B}I:Sp1-SP", "SR:C10-MG{PS:CL1B}I:Sp2-SP", "SR:C10-MG{PS:CL2B}I:Sp1-SP", "SR:C10-MG{PS:CL2B}I:Sp2-SP", "SR:C10-MG{PS:CM1A}I:Sp1-SP", "SR:C10-MG{PS:CM1A}I:Sp2-SP", "SR:C10-MG{PS:CM1B}I:Sp1-SP", "SR:C10-MG{PS:CM1B}I:Sp2-SP", "SR:C10-MG{PS:QH1A}I:Sp1-SP", "SR:C10-MG{PS:QH2A}I:Sp1-SP", "SR:C10-MG{PS:QH3A}I:Sp1-SP", "SR:C10-MG{PS:QL1B}I:Sp1-SP", "SR:C10-MG{PS:QL2B}I:Sp1-SP", "SR:C10-MG{PS:QL3B}I:Sp1-SP", "SR:C10-MG{PS:QM1A}I:Sp1-SP", "SR:C10-MG{PS:QM1B}I:Sp1-SP", "SR:C10-MG{PS:QM2A}I:Sp1-SP", "SR:C10-MG{PS:QM2B}I:Sp1-SP", "SR:C10-MG{PS:SL1-P3}I:Sp1-SP", "SR:C10-MG{PS:SQKH1A}I:Sp1-SP", "SR:C11-MG{PS:BT1A}I:Sp1-SP", "SR:C11-MG{PS:BT1A}I:Sp2-SP", "SR:C11-MG{PS:CH1B}I:Sp1-SP", "SR:C11-MG{PS:CH1B}I:Sp2-SP", "SR:C11-MG{PS:CH2B}I:Sp1-SP", "SR:C11-MG{PS:CH2B}I:Sp2-SP", "SR:C11-MG{PS:CL1A}I:Sp1-SP", "SR:C11-MG{PS:CL1A}I:Sp2-SP", "SR:C11-MG{PS:CL2A}I:Sp1-SP", "SR:C11-MG{PS:CL2A}I:Sp2-SP", "SR:C11-MG{PS:CM1A}I:Sp1-SP", "SR:C11-MG{PS:CM1A}I:Sp2-SP", "SR:C11-MG{PS:CM1B}I:Sp1-SP", "SR:C11-MG{PS:CM1B}I:Sp2-SP", "SR:C11-MG{PS:QH1B}I:Sp1-SP", "SR:C11-MG{PS:QH2B}I:Sp1-SP", "SR:C11-MG{PS:QH3B}I:Sp1-SP", "SR:C11-MG{PS:QL1A}I:Sp1-SP", "SR:C11-MG{PS:QL2A}I:Sp1-SP", "SR:C11-MG{PS:QL3A}I:Sp1-SP", "SR:C11-MG{PS:QM1A}I:Sp1-SP", "SR:C11-MG{PS:QM1B}I:Sp1-SP", "SR:C11-MG{PS:QM2A}I:Sp1-SP", "SR:C11-MG{PS:QM2B}I:Sp1-SP", "SR:C11-MG{PS:SQKM1A}I:Sp1-SP", "SR:C12-MG{PS:BT1A}I:Sp1-SP", "SR:C12-MG{PS:BT1A}I:Sp2-SP", "SR:C12-MG{PS:CH1A}I:Sp1-SP", "SR:C12-MG{PS:CH1A}I:Sp2-SP", "SR:C12-MG{PS:CH2A}I:Sp1-SP", "SR:C12-MG{PS:CH2A}I:Sp2-SP", "SR:C12-MG{PS:CL1B}I:Sp1-SP", "SR:C12-MG{PS:CL1B}I:Sp2-SP", "SR:C12-MG{PS:CL2B}I:Sp1-SP", "SR:C12-MG{PS:CL2B}I:Sp2-SP", "SR:C12-MG{PS:CM1A}I:Sp1-SP", "SR:C12-MG{PS:CM1A}I:Sp2-SP", "SR:C12-MG{PS:CM1B}I:Sp1-SP", "SR:C12-MG{PS:CM1B}I:Sp2-SP", "SR:C12-MG{PS:QH1A}I:Sp1-SP", "SR:C12-MG{PS:QH2A}I:Sp1-SP", "SR:C12-MG{PS:QH3A}I:Sp1-SP", "SR:C12-MG{PS:QL1B}I:Sp1-SP", "SR:C12-MG{PS:QL2B}I:Sp1-SP", "SR:C12-MG{PS:QL3B}I:Sp1-SP", "SR:C12-MG{PS:QM1A}I:Sp1-SP", "SR:C12-MG{PS:QM1B}I:Sp1-SP", "SR:C12-MG{PS:QM2A}I:Sp1-SP", "SR:C12-MG{PS:QM2B}I:Sp1-SP", "SR:C12-MG{PS:SH1-P4}I:Sp1-SP", "SR:C12-MG{PS:SH3-P4}I:Sp1-SP", "SR:C12-MG{PS:SQKH1A}I:Sp1-SP", "SR:C13-MG{PS:BT1A}I:Sp1-SP", "SR:C13-MG{PS:BT1A}I:Sp2-SP", "SR:C13-MG{PS:CH1B}I:Sp1-SP", "SR:C13-MG{PS:CH1B}I:Sp2-SP", "SR:C13-MG{PS:CH2B}I:Sp1-SP", "SR:C13-MG{PS:CH2B}I:Sp2-SP", "SR:C13-MG{PS:CL1A}I:Sp1-SP", "SR:C13-MG{PS:CL1A}I:Sp2-SP", "SR:C13-MG{PS:CL2A}I:Sp1-SP", "SR:C13-MG{PS:CL2A}I:Sp2-SP", "SR:C13-MG{PS:CM1A}I:Sp1-SP", "SR:C13-MG{PS:CM1A}I:Sp2-SP", "SR:C13-MG{PS:CM1B}I:Sp1-SP", "SR:C13-MG{PS:CM1B}I:Sp2-SP", "SR:C13-MG{PS:QH1B}I:Sp1-SP", "SR:C13-MG{PS:QH2B}I:Sp1-SP", "SR:C13-MG{PS:QH3B}I:Sp1-SP", "SR:C13-MG{PS:QL1A}I:Sp1-SP", "SR:C13-MG{PS:QL2A}I:Sp1-SP", "SR:C13-MG{PS:QL3A}I:Sp1-SP", "SR:C13-MG{PS:QM1A}I:Sp1-SP", "SR:C13-MG{PS:QM1B}I:Sp1-SP", "SR:C13-MG{PS:QM2A}I:Sp1-SP", "SR:C13-MG{PS:QM2B}I:Sp1-SP", "SR:C13-MG{PS:SH4-P4}I:Sp1-SP", "SR:C13-MG{PS:SM1A-P4}I:Sp1-SP", "SR:C13-MG{PS:SQKM1A}I:Sp1-SP", "SR:C14-MG{PS:BT1A}I:Sp1-SP", "SR:C14-MG{PS:BT1A}I:Sp2-SP", "SR:C14-MG{PS:CH1A}I:Sp1-SP", "SR:C14-MG{PS:CH1A}I:Sp2-SP", "SR:C14-MG{PS:CH2A}I:Sp1-SP", "SR:C14-MG{PS:CH2A}I:Sp2-SP", "SR:C14-MG{PS:CL1B}I:Sp1-SP", "SR:C14-MG{PS:CL1B}I:Sp2-SP", "SR:C14-MG{PS:CL2B}I:Sp1-SP", "SR:C14-MG{PS:CL2B}I:Sp2-SP", "SR:C14-MG{PS:CM1A}I:Sp1-SP", "SR:C14-MG{PS:CM1A}I:Sp2-SP", "SR:C14-MG{PS:CM1B}I:Sp1-SP", "SR:C14-MG{PS:CM1B}I:Sp2-SP", "SR:C14-MG{PS:QH1A}I:Sp1-SP", "SR:C14-MG{PS:QH2A}I:Sp1-SP", "SR:C14-MG{PS:QH3A}I:Sp1-SP", "SR:C14-MG{PS:QL1B}I:Sp1-SP", "SR:C14-MG{PS:QL2B}I:Sp1-SP", "SR:C14-MG{PS:QL3B}I:Sp1-SP", "SR:C14-MG{PS:QM1A}I:Sp1-SP", "SR:C14-MG{PS:QM1B}I:Sp1-SP", "SR:C14-MG{PS:QM2A}I:Sp1-SP", "SR:C14-MG{PS:QM2B}I:Sp1-SP", "SR:C14-MG{PS:SM1B-P4}I:Sp1-SP", "SR:C14-MG{PS:SM2B-P4}I:Sp1-SP", "SR:C14-MG{PS:SQKH1A}I:Sp1-SP", "SR:C15-MG{PS:BT1A}I:Sp1-SP", "SR:C15-MG{PS:BT1A}I:Sp2-SP", "SR:C15-MG{PS:CH1B}I:Sp1-SP", "SR:C15-MG{PS:CH1B}I:Sp2-SP", "SR:C15-MG{PS:CH2B}I:Sp1-SP", "SR:C15-MG{PS:CH2B}I:Sp2-SP", "SR:C15-MG{PS:CL1A}I:Sp1-SP", "SR:C15-MG{PS:CL1A}I:Sp2-SP", "SR:C15-MG{PS:CL2A}I:Sp1-SP", "SR:C15-MG{PS:CL2A}I:Sp2-SP", "SR:C15-MG{PS:CM1A}I:Sp1-SP", "SR:C15-MG{PS:CM1A}I:Sp2-SP", "SR:C15-MG{PS:CM1B}I:Sp1-SP", "SR:C15-MG{PS:CM1B}I:Sp2-SP", "SR:C15-MG{PS:QH1B}I:Sp1-SP", "SR:C15-MG{PS:QH2B}I:Sp1-SP", "SR:C15-MG{PS:QH3B}I:Sp1-SP", "SR:C15-MG{PS:QL1A}I:Sp1-SP", "SR:C15-MG{PS:QL2A}I:Sp1-SP", "SR:C15-MG{PS:QL3A}I:Sp1-SP", "SR:C15-MG{PS:QM1A}I:Sp1-SP", "SR:C15-MG{PS:QM1B}I:Sp1-SP", "SR:C15-MG{PS:QM2A}I:Sp1-SP", "SR:C15-MG{PS:QM2B}I:Sp1-SP", "SR:C15-MG{PS:SL2-P4}I:Sp1-SP", "SR:C15-MG{PS:SL3-P4}I:Sp1-SP", "SR:C15-MG{PS:SQKM1A}I:Sp1-SP", "SR:C16-MG{PS:BT1A}I:Sp1-SP", "SR:C16-MG{PS:BT1A}I:Sp2-SP", "SR:C16-MG{PS:CH1A}I:Sp1-SP", "SR:C16-MG{PS:CH1A}I:Sp2-SP", "SR:C16-MG{PS:CH2A}I:Sp1-SP", "SR:C16-MG{PS:CH2A}I:Sp2-SP", "SR:C16-MG{PS:CL1B}I:Sp1-SP", "SR:C16-MG{PS:CL1B}I:Sp2-SP", "SR:C16-MG{PS:CL2B}I:Sp1-SP", "SR:C16-MG{PS:CL2B}I:Sp2-SP", "SR:C16-MG{PS:CM1A}I:Sp1-SP", "SR:C16-MG{PS:CM1A}I:Sp2-SP", "SR:C16-MG{PS:CM1B}I:Sp1-SP", "SR:C16-MG{PS:CM1B}I:Sp2-SP", "SR:C16-MG{PS:QH1A}I:Sp1-SP", "SR:C16-MG{PS:QH2A}I:Sp1-SP", "SR:C16-MG{PS:QH3A}I:Sp1-SP", "SR:C16-MG{PS:QL1B}I:Sp1-SP", "SR:C16-MG{PS:QL2B}I:Sp1-SP", "SR:C16-MG{PS:QL3B}I:Sp1-SP", "SR:C16-MG{PS:QM1A}I:Sp1-SP", "SR:C16-MG{PS:QM1B}I:Sp1-SP", "SR:C16-MG{PS:QM2A}I:Sp1-SP", "SR:C16-MG{PS:QM2B}I:Sp1-SP", "SR:C16-MG{PS:SL1-P4}I:Sp1-SP", "SR:C16-MG{PS:SQKH1A}I:Sp1-SP", "SR:C17-MG{PS:BT1A}I:Sp1-SP", "SR:C17-MG{PS:BT1A}I:Sp2-SP", "SR:C17-MG{PS:CH1B}I:Sp1-SP", "SR:C17-MG{PS:CH1B}I:Sp2-SP", "SR:C17-MG{PS:CH2B}I:Sp1-SP", "SR:C17-MG{PS:CH2B}I:Sp2-SP", "SR:C17-MG{PS:CL1A}I:Sp1-SP", "SR:C17-MG{PS:CL1A}I:Sp2-SP", "SR:C17-MG{PS:CL2A}I:Sp1-SP", "SR:C17-MG{PS:CL2A}I:Sp2-SP", "SR:C17-MG{PS:CM1A}I:Sp1-SP", "SR:C17-MG{PS:CM1A}I:Sp2-SP", "SR:C17-MG{PS:CM1B}I:Sp1-SP", "SR:C17-MG{PS:CM1B}I:Sp2-SP", "SR:C17-MG{PS:QH1B}I:Sp1-SP", "SR:C17-MG{PS:QH2B}I:Sp1-SP", "SR:C17-MG{PS:QH3B}I:Sp1-SP", "SR:C17-MG{PS:QL1A}I:Sp1-SP", "SR:C17-MG{PS:QL2A}I:Sp1-SP", "SR:C17-MG{PS:QL3A}I:Sp1-SP", "SR:C17-MG{PS:QM1A}I:Sp1-SP", "SR:C17-MG{PS:QM1B}I:Sp1-SP", "SR:C17-MG{PS:QM2A}I:Sp1-SP", "SR:C17-MG{PS:QM2B}I:Sp1-SP", "SR:C17-MG{PS:SQKM1A}I:Sp1-SP", "SR:C18-MG{PS:BT1A}I:Sp1-SP", "SR:C18-MG{PS:BT1A}I:Sp2-SP", "SR:C18-MG{PS:CH1A}I:Sp1-SP", "SR:C18-MG{PS:CH1A}I:Sp2-SP", "SR:C18-MG{PS:CH2A}I:Sp1-SP", "SR:C18-MG{PS:CH2A}I:Sp2-SP", "SR:C18-MG{PS:CL1B}I:Sp1-SP", "SR:C18-MG{PS:CL1B}I:Sp2-SP", "SR:C18-MG{PS:CL2B}I:Sp1-SP", "SR:C18-MG{PS:CL2B}I:Sp2-SP", "SR:C18-MG{PS:CM1A}I:Sp1-SP", "SR:C18-MG{PS:CM1A}I:Sp2-SP", "SR:C18-MG{PS:CM1B}I:Sp1-SP", "SR:C18-MG{PS:CM1B}I:Sp2-SP", "SR:C18-MG{PS:QH1A}I:Sp1-SP", "SR:C18-MG{PS:QH2A}I:Sp1-SP", "SR:C18-MG{PS:QH3A}I:Sp1-SP", "SR:C18-MG{PS:QL1B}I:Sp1-SP", "SR:C18-MG{PS:QL2B}I:Sp1-SP", "SR:C18-MG{PS:QL3B}I:Sp1-SP", "SR:C18-MG{PS:QM1A}I:Sp1-SP", "SR:C18-MG{PS:QM1B}I:Sp1-SP", "SR:C18-MG{PS:QM2A}I:Sp1-SP", "SR:C18-MG{PS:QM2B}I:Sp1-SP", "SR:C18-MG{PS:SH1-DW18}I:Sp1-SP", "SR:C18-MG{PS:SH1-P5}I:Sp1-SP", "SR:C18-MG{PS:SH3-DW18}I:Sp1-SP", "SR:C18-MG{PS:SH3-P5}I:Sp1-SP", "SR:C18-MG{PS:SH4-DW18}I:Sp1-SP", "SR:C18-MG{PS:SQKH1A}I:Sp1-SP", "SR:C19-MG{PS:BT1A}I:Sp1-SP", "SR:C19-MG{PS:BT1A}I:Sp2-SP", "SR:C19-MG{PS:CH1B}I:Sp1-SP", "SR:C19-MG{PS:CH1B}I:Sp2-SP", "SR:C19-MG{PS:CH2B}I:Sp1-SP", "SR:C19-MG{PS:CH2B}I:Sp2-SP", "SR:C19-MG{PS:CL1A}I:Sp1-SP", "SR:C19-MG{PS:CL1A}I:Sp2-SP", "SR:C19-MG{PS:CL2A}I:Sp1-SP", "SR:C19-MG{PS:CL2A}I:Sp2-SP", "SR:C19-MG{PS:CM1A}I:Sp1-SP", "SR:C19-MG{PS:CM1A}I:Sp2-SP", "SR:C19-MG{PS:CM1B}I:Sp1-SP", "SR:C19-MG{PS:CM1B}I:Sp2-SP", "SR:C19-MG{PS:QH1B}I:Sp1-SP", "SR:C19-MG{PS:QH2B}I:Sp1-SP", "SR:C19-MG{PS:QH3B}I:Sp1-SP", "SR:C19-MG{PS:QL1A}I:Sp1-SP", "SR:C19-MG{PS:QL2A}I:Sp1-SP", "SR:C19-MG{PS:QL3A}I:Sp1-SP", "SR:C19-MG{PS:QM1A}I:Sp1-SP", "SR:C19-MG{PS:QM1B}I:Sp1-SP", "SR:C19-MG{PS:QM2A}I:Sp1-SP", "SR:C19-MG{PS:QM2B}I:Sp1-SP", "SR:C19-MG{PS:SH4-P5}I:Sp1-SP", "SR:C19-MG{PS:SM1A-P5}I:Sp1-SP", "SR:C19-MG{PS:SQKM1A}I:Sp1-SP", "SR:C20-MG{PS:BT1A}I:Sp1-SP", "SR:C20-MG{PS:BT1A}I:Sp2-SP", "SR:C20-MG{PS:CH1A}I:Sp1-SP", "SR:C20-MG{PS:CH1A}I:Sp2-SP", "SR:C20-MG{PS:CH2A}I:Sp1-SP", "SR:C20-MG{PS:CH2A}I:Sp2-SP", "SR:C20-MG{PS:CL1B}I:Sp1-SP", "SR:C20-MG{PS:CL1B}I:Sp2-SP", "SR:C20-MG{PS:CL2B}I:Sp1-SP", "SR:C20-MG{PS:CL2B}I:Sp2-SP", "SR:C20-MG{PS:CM1A}I:Sp1-SP", "SR:C20-MG{PS:CM1A}I:Sp2-SP", "SR:C20-MG{PS:CM1B}I:Sp1-SP", "SR:C20-MG{PS:CM1B}I:Sp2-SP", "SR:C20-MG{PS:QH1A}I:Sp1-SP", "SR:C20-MG{PS:QH2A}I:Sp1-SP", "SR:C20-MG{PS:QH3A}I:Sp1-SP", "SR:C20-MG{PS:QL1B}I:Sp1-SP", "SR:C20-MG{PS:QL2B}I:Sp1-SP", "SR:C20-MG{PS:QL3B}I:Sp1-SP", "SR:C20-MG{PS:QM1A}I:Sp1-SP", "SR:C20-MG{PS:QM1B}I:Sp1-SP", "SR:C20-MG{PS:QM2A}I:Sp1-SP", "SR:C20-MG{PS:QM2B}I:Sp1-SP", "SR:C20-MG{PS:SM1B-P5}I:Sp1-SP", "SR:C20-MG{PS:SM2B-P5}I:Sp1-SP", "SR:C20-MG{PS:SQKH1A}I:Sp1-SP", "SR:C21-MG{PS:BT1A}I:Sp1-SP", "SR:C21-MG{PS:BT1A}I:Sp2-SP", "SR:C21-MG{PS:CH1B}I:Sp1-SP", "SR:C21-MG{PS:CH1B}I:Sp2-SP", "SR:C21-MG{PS:CH2B}I:Sp1-SP", "SR:C21-MG{PS:CH2B}I:Sp2-SP", "SR:C21-MG{PS:CL1A}I:Sp1-SP", "SR:C21-MG{PS:CL1A}I:Sp2-SP", "SR:C21-MG{PS:CL2A}I:Sp1-SP", "SR:C21-MG{PS:CL2A}I:Sp2-SP", "SR:C21-MG{PS:CM1A}I:Sp1-SP", "SR:C21-MG{PS:CM1A}I:Sp2-SP", "SR:C21-MG{PS:CM1B}I:Sp1-SP", "SR:C21-MG{PS:CM1B}I:Sp2-SP", "SR:C21-MG{PS:QH1B}I:Sp1-SP", "SR:C21-MG{PS:QH2B}I:Sp1-SP", "SR:C21-MG{PS:QH3B}I:Sp1-SP", "SR:C21-MG{PS:QL1A}I:Sp1-SP", "SR:C21-MG{PS:QL2A}I:Sp1-SP", "SR:C21-MG{PS:QL3A}I:Sp1-SP", "SR:C21-MG{PS:QM1A}I:Sp1-SP", "SR:C21-MG{PS:QM1B}I:Sp1-SP", "SR:C21-MG{PS:QM2A}I:Sp1-SP", "SR:C21-MG{PS:QM2B}I:Sp1-SP", "SR:C21-MG{PS:SL2-P5}I:Sp1-SP", "SR:C21-MG{PS:SL3-P5}I:Sp1-SP", "SR:C21-MG{PS:SQKM1A}I:Sp1-SP", "SR:C22-MG{PS:BT1A}I:Sp1-SP", "SR:C22-MG{PS:BT1A}I:Sp2-SP", "SR:C22-MG{PS:CH1A}I:Sp1-SP", "SR:C22-MG{PS:CH1A}I:Sp2-SP", "SR:C22-MG{PS:CH2A}I:Sp1-SP", "SR:C22-MG{PS:CH2A}I:Sp2-SP", "SR:C22-MG{PS:CL1B}I:Sp1-SP", "SR:C22-MG{PS:CL1B}I:Sp2-SP", "SR:C22-MG{PS:CL2B}I:Sp1-SP", "SR:C22-MG{PS:CL2B}I:Sp2-SP", "SR:C22-MG{PS:CM1A}I:Sp1-SP", "SR:C22-MG{PS:CM1A}I:Sp2-SP", "SR:C22-MG{PS:CM1B}I:Sp1-SP", "SR:C22-MG{PS:CM1B}I:Sp2-SP", "SR:C22-MG{PS:QH1A}I:Sp1-SP", "SR:C22-MG{PS:QH2A}I:Sp1-SP", "SR:C22-MG{PS:QH3A}I:Sp1-SP", "SR:C22-MG{PS:QL1B}I:Sp1-SP", "SR:C22-MG{PS:QL2B}I:Sp1-SP", "SR:C22-MG{PS:QL3B}I:Sp1-SP", "SR:C22-MG{PS:QM1A}I:Sp1-SP", "SR:C22-MG{PS:QM1B}I:Sp1-SP", "SR:C22-MG{PS:QM2A}I:Sp1-SP", "SR:C22-MG{PS:QM2B}I:Sp1-SP", "SR:C22-MG{PS:SL1-P5}I:Sp1-SP", "SR:C22-MG{PS:SQKH1A}I:Sp1-SP", "SR:C23-MG{PS:BT1A}I:Sp1-SP", "SR:C23-MG{PS:BT1A}I:Sp2-SP", "SR:C23-MG{PS:CH1B}I:Sp1-SP", "SR:C23-MG{PS:CH1B}I:Sp2-SP", "SR:C23-MG{PS:CH2B}I:Sp1-SP", "SR:C23-MG{PS:CH2B}I:Sp2-SP", "SR:C23-MG{PS:CL1A}I:Sp1-SP", "SR:C23-MG{PS:CL1A}I:Sp2-SP", "SR:C23-MG{PS:CL2A}I:Sp1-SP", "SR:C23-MG{PS:CL2A}I:Sp2-SP", "SR:C23-MG{PS:CM1A}I:Sp1-SP", "SR:C23-MG{PS:CM1A}I:Sp2-SP", "SR:C23-MG{PS:CM1B}I:Sp1-SP", "SR:C23-MG{PS:CM1B}I:Sp2-SP", "SR:C23-MG{PS:QH1B}I:Sp1-SP", "SR:C23-MG{PS:QH2B}I:Sp1-SP", "SR:C23-MG{PS:QH3B}I:Sp1-SP", "SR:C23-MG{PS:QL1A}I:Sp1-SP", "SR:C23-MG{PS:QL2A}I:Sp1-SP", "SR:C23-MG{PS:QL3A}I:Sp1-SP", "SR:C23-MG{PS:QM1A}I:Sp1-SP", "SR:C23-MG{PS:QM1B}I:Sp1-SP", "SR:C23-MG{PS:QM2A}I:Sp1-SP", "SR:C23-MG{PS:QM2B}I:Sp1-SP", "SR:C23-MG{PS:SQKM1A}I:Sp1-SP", "SR:C24-MG{PS:BT1A}I:Sp1-SP", "SR:C24-MG{PS:BT1A}I:Sp2-SP", "SR:C24-MG{PS:CH1A}I:Sp1-SP", "SR:C24-MG{PS:CH1A}I:Sp2-SP", "SR:C24-MG{PS:CH2A}I:Sp1-SP", "SR:C24-MG{PS:CH2A}I:Sp2-SP", "SR:C24-MG{PS:CL1B}I:Sp1-SP", "SR:C24-MG{PS:CL1B}I:Sp2-SP", "SR:C24-MG{PS:CL2B}I:Sp1-SP", "SR:C24-MG{PS:CL2B}I:Sp2-SP", "SR:C24-MG{PS:CM1A}I:Sp1-SP", "SR:C24-MG{PS:CM1A}I:Sp2-SP", "SR:C24-MG{PS:CM1B}I:Sp1-SP", "SR:C24-MG{PS:CM1B}I:Sp2-SP", "SR:C24-MG{PS:QH1A}I:Sp1-SP", "SR:C24-MG{PS:QH2A}I:Sp1-SP", "SR:C24-MG{PS:QH3A}I:Sp1-SP", "SR:C24-MG{PS:QL1B}I:Sp1-SP", "SR:C24-MG{PS:QL2B}I:Sp1-SP", "SR:C24-MG{PS:QL3B}I:Sp1-SP", "SR:C24-MG{PS:QM1A}I:Sp1-SP", "SR:C24-MG{PS:QM1B}I:Sp1-SP", "SR:C24-MG{PS:QM2A}I:Sp1-SP", "SR:C24-MG{PS:QM2B}I:Sp1-SP", "SR:C24-MG{PS:SH1-P1}I:Sp1-SP", "SR:C24-MG{PS:SH3-P1}I:Sp1-SP", "SR:C24-MG{PS:SQKH1A}I:Sp1-SP", "SR:C25-MG{PS:BT1A}I:Sp1-SP", "SR:C25-MG{PS:BT1A}I:Sp2-SP", "SR:C25-MG{PS:CH1B}I:Sp1-SP", "SR:C25-MG{PS:CH1B}I:Sp2-SP", "SR:C25-MG{PS:CH2B}I:Sp1-SP", "SR:C25-MG{PS:CH2B}I:Sp2-SP", "SR:C25-MG{PS:CL1A}I:Sp1-SP", "SR:C25-MG{PS:CL1A}I:Sp2-SP", "SR:C25-MG{PS:CL2A}I:Sp1-SP", "SR:C25-MG{PS:CL2A}I:Sp2-SP", "SR:C25-MG{PS:CM1A}I:Sp1-SP", "SR:C25-MG{PS:CM1A}I:Sp2-SP", "SR:C25-MG{PS:CM1B}I:Sp1-SP", "SR:C25-MG{PS:CM1B}I:Sp2-SP", "SR:C25-MG{PS:QH1B}I:Sp1-SP", "SR:C25-MG{PS:QH2B}I:Sp1-SP", "SR:C25-MG{PS:QH3B}I:Sp1-SP", "SR:C25-MG{PS:QL1A}I:Sp1-SP", "SR:C25-MG{PS:QL2A}I:Sp1-SP", "SR:C25-MG{PS:QL3A}I:Sp1-SP", "SR:C25-MG{PS:QM1A}I:Sp1-SP", "SR:C25-MG{PS:QM1B}I:Sp1-SP", "SR:C25-MG{PS:QM2A}I:Sp1-SP", "SR:C25-MG{PS:QM2B}I:Sp1-SP", "SR:C25-MG{PS:SH4-P1}I:Sp1-SP", "SR:C25-MG{PS:SM1A-P1}I:Sp1-SP", "SR:C25-MG{PS:SQKM1A}I:Sp1-SP", "SR:C26-MG{PS:BT1A}I:Sp1-SP", "SR:C26-MG{PS:BT1A}I:Sp2-SP", "SR:C26-MG{PS:CH1A}I:Sp1-SP", "SR:C26-MG{PS:CH1A}I:Sp2-SP", "SR:C26-MG{PS:CH2A}I:Sp1-SP", "SR:C26-MG{PS:CH2A}I:Sp2-SP", "SR:C26-MG{PS:CL1B}I:Sp1-SP", "SR:C26-MG{PS:CL1B}I:Sp2-SP", "SR:C26-MG{PS:CL2B}I:Sp1-SP", "SR:C26-MG{PS:CL2B}I:Sp2-SP", "SR:C26-MG{PS:CM1A}I:Sp1-SP", "SR:C26-MG{PS:CM1A}I:Sp2-SP", "SR:C26-MG{PS:CM1B}I:Sp1-SP", "SR:C26-MG{PS:CM1B}I:Sp2-SP", "SR:C26-MG{PS:QH1A}I:Sp1-SP", "SR:C26-MG{PS:QH2A}I:Sp1-SP", "SR:C26-MG{PS:QH3A}I:Sp1-SP", "SR:C26-MG{PS:QL1B}I:Sp1-SP", "SR:C26-MG{PS:QL2B}I:Sp1-SP", "SR:C26-MG{PS:QL3B}I:Sp1-SP", "SR:C26-MG{PS:QM1A}I:Sp1-SP", "SR:C26-MG{PS:QM1B}I:Sp1-SP", "SR:C26-MG{PS:QM2A}I:Sp1-SP", "SR:C26-MG{PS:QM2B}I:Sp1-SP", "SR:C26-MG{PS:SM1B-P1}I:Sp1-SP", "SR:C26-MG{PS:SM2B-P1}I:Sp1-SP", "SR:C26-MG{PS:SQKH1A}I:Sp1-SP", "SR:C27-MG{PS:BT1A}I:Sp1-SP", "SR:C27-MG{PS:BT1A}I:Sp2-SP", "SR:C27-MG{PS:CH1B}I:Sp1-SP", "SR:C27-MG{PS:CH1B}I:Sp2-SP", "SR:C27-MG{PS:CH2B}I:Sp1-SP", "SR:C27-MG{PS:CH2B}I:Sp2-SP", "SR:C27-MG{PS:CL1A}I:Sp1-SP", "SR:C27-MG{PS:CL1A}I:Sp2-SP", "SR:C27-MG{PS:CL2A}I:Sp1-SP", "SR:C27-MG{PS:CL2A}I:Sp2-SP", "SR:C27-MG{PS:CM1A}I:Sp1-SP", "SR:C27-MG{PS:CM1A}I:Sp2-SP", "SR:C27-MG{PS:CM1B}I:Sp1-SP", "SR:C27-MG{PS:CM1B}I:Sp2-SP", "SR:C27-MG{PS:QH1B}I:Sp1-SP", "SR:C27-MG{PS:QH2B}I:Sp1-SP", "SR:C27-MG{PS:QH3B}I:Sp1-SP", "SR:C27-MG{PS:QL1A}I:Sp1-SP", "SR:C27-MG{PS:QL2A}I:Sp1-SP", "SR:C27-MG{PS:QL3A}I:Sp1-SP", "SR:C27-MG{PS:QM1A}I:Sp1-SP", "SR:C27-MG{PS:QM1B}I:Sp1-SP", "SR:C27-MG{PS:QM2A}I:Sp1-SP", "SR:C27-MG{PS:QM2B}I:Sp1-SP", "SR:C27-MG{PS:SL2-P1}I:Sp1-SP", "SR:C27-MG{PS:SL3-P1}I:Sp1-SP", "SR:C27-MG{PS:SQKM1A}I:Sp1-SP", "SR:C28-MG{PS:BT1A}I:Sp1-SP", "SR:C28-MG{PS:BT1A}I:Sp2-SP", "SR:C28-MG{PS:CH1A}I:Sp1-SP", "SR:C28-MG{PS:CH1A}I:Sp2-SP", "SR:C28-MG{PS:CH2A}I:Sp1-SP", "SR:C28-MG{PS:CH2A}I:Sp2-SP", "SR:C28-MG{PS:CL1B}I:Sp1-SP", "SR:C28-MG{PS:CL1B}I:Sp2-SP", "SR:C28-MG{PS:CL2B}I:Sp1-SP", "SR:C28-MG{PS:CL2B}I:Sp2-SP", "SR:C28-MG{PS:CM1A}I:Sp1-SP", "SR:C28-MG{PS:CM1A}I:Sp2-SP", "SR:C28-MG{PS:CM1B}I:Sp1-SP", "SR:C28-MG{PS:CM1B}I:Sp2-SP", "SR:C28-MG{PS:QH1A}I:Sp1-SP", "SR:C28-MG{PS:QH2A}I:Sp1-SP", "SR:C28-MG{PS:QH3A}I:Sp1-SP", "SR:C28-MG{PS:QL1B}I:Sp1-SP", "SR:C28-MG{PS:QL2B}I:Sp1-SP", "SR:C28-MG{PS:QL3B}I:Sp1-SP", "SR:C28-MG{PS:QM1A}I:Sp1-SP", "SR:C28-MG{PS:QM1B}I:Sp1-SP", "SR:C28-MG{PS:QM2A}I:Sp1-SP", "SR:C28-MG{PS:QM2B}I:Sp1-SP", "SR:C28-MG{PS:SH1-DW28}I:Sp1-SP", "SR:C28-MG{PS:SH3-DW28}I:Sp1-SP", "SR:C28-MG{PS:SH4-DW28}I:Sp1-SP", "SR:C28-MG{PS:SL1-P1}I:Sp1-SP", "SR:C28-MG{PS:SQKH1A}I:Sp1-SP", "SR:C29-MG{PS:BT1A}I:Sp1-SP", "SR:C29-MG{PS:BT1A}I:Sp2-SP", "SR:C29-MG{PS:CH1B}I:Sp1-SP", "SR:C29-MG{PS:CH1B}I:Sp2-SP", "SR:C29-MG{PS:CH2B}I:Sp1-SP", "SR:C29-MG{PS:CH2B}I:Sp2-SP", "SR:C29-MG{PS:CL1A}I:Sp1-SP", "SR:C29-MG{PS:CL1A}I:Sp2-SP", "SR:C29-MG{PS:CL2A}I:Sp1-SP", "SR:C29-MG{PS:CL2A}I:Sp2-SP", "SR:C29-MG{PS:CM1A}I:Sp1-SP", "SR:C29-MG{PS:CM1A}I:Sp2-SP", "SR:C29-MG{PS:CM1B}I:Sp1-SP", "SR:C29-MG{PS:CM1B}I:Sp2-SP", "SR:C29-MG{PS:QH1B}I:Sp1-SP", "SR:C29-MG{PS:QH2B}I:Sp1-SP", "SR:C29-MG{PS:QH3B}I:Sp1-SP", "SR:C29-MG{PS:QL1A}I:Sp1-SP", "SR:C29-MG{PS:QL2A}I:Sp1-SP", "SR:C29-MG{PS:QL3A}I:Sp1-SP", "SR:C29-MG{PS:QM1A}I:Sp1-SP", "SR:C29-MG{PS:QM1B}I:Sp1-SP", "SR:C29-MG{PS:QM2A}I:Sp1-SP", "SR:C29-MG{PS:QM2B}I:Sp1-SP", "SR:C29-MG{PS:SQKM1A}I:Sp1-SP", "SR:C30-MG{PS:BT1A}I:Sp1-SP", "SR:C30-MG{PS:BT1A}I:Sp2-SP", "SR:C30-MG{PS:CH1A}I:Sp1-SP", "SR:C30-MG{PS:CH1A}I:Sp2-SP", "SR:C30-MG{PS:CH2A}I:Sp1-SP", "SR:C30-MG{PS:CH2A}I:Sp2-SP", "SR:C30-MG{PS:CL1B}I:Sp1-SP", "SR:C30-MG{PS:CL1B}I:Sp2-SP", "SR:C30-MG{PS:CL2B}I:Sp1-SP", "SR:C30-MG{PS:CL2B}I:Sp2-SP", "SR:C30-MG{PS:CM1A}I:Sp1-SP", "SR:C30-MG{PS:CM1A}I:Sp2-SP", "SR:C30-MG{PS:CM1B}I:Sp1-SP", "SR:C30-MG{PS:CM1B}I:Sp2-SP", "SR:C30-MG{PS:QH1A}I:Sp1-SP", "SR:C30-MG{PS:QH2A}I:Sp1-SP", "SR:C30-MG{PS:QH3A}I:Sp1-SP", "SR:C30-MG{PS:QL1B}I:Sp1-SP", "SR:C30-MG{PS:QL2B}I:Sp1-SP", "SR:C30-MG{PS:QL3B}I:Sp1-SP", "SR:C30-MG{PS:QM1A}I:Sp1-SP", "SR:C30-MG{PS:QM1B}I:Sp1-SP", "SR:C30-MG{PS:QM2A}I:Sp1-SP", "SR:C30-MG{PS:QM2B}I:Sp1-SP", "SR:C30-MG{PS:SH1-P2}I:Sp1-SP", "SR:C30-MG{PS:SH3-P2}I:Sp1-SP", "SR:C30-MG{PS:SQKH1A}I:Sp1-SP" ] pvs0 = [ 'SR:C01-MG{PS:SM1A-P2}I:Sp1-SP', 'SR:C02-MG{PS:SM1B-P2}I:Sp1-SP', 'SR:C02-MG{PS:SM2B-P2}I:Sp1-SP', 'SR:C07-MG{PS:SM1A-P3}I:Sp1-SP', 'SR:C08-MG{PS:SM1B-P3}I:Sp1-SP', 'SR:C08-MG{PS:SM2B-P3}I:Sp1-SP', 'SR:C13-MG{PS:SM1A-P4}I:Sp1-SP', 'SR:C14-MG{PS:SM1B-P4}I:Sp1-SP', 'SR:C14-MG{PS:SM2B-P4}I:Sp1-SP', 'SR:C19-MG{PS:SM1A-P5}I:Sp1-SP', 'SR:C20-MG{PS:SM1B-P5}I:Sp1-SP', 'SR:C20-MG{PS:SM2B-P5}I:Sp1-SP', 'SR:C25-MG{PS:SM1A-P1}I:Sp1-SP', 'SR:C26-MG{PS:SM1B-P1}I:Sp1-SP', 'SR:C26-MG{PS:SM2B-P1}I:Sp1-SP' ] with self.assertRaises(KeyError) as context: updateconfig(self.conn, self.collection, name, pvlist={"name": pvs0}) self.assertEqual(context.exception.message, 'Cannot find key ("names") for pv names.') self.assertTrue( updateconfig(self.conn, self.collection, name, pvlist={"names": pvs})) res3 = retrieveconfig(self.conn, self.collection, name, withpvs=True) self.assertEqual(res3[0]["status"], "active") self.assertNotEqual(res1[0]["updated_on"], res2[0]["updated_on"]) self.assertEqual(res3[0]["created_on"], res0[0]["created_on"]) self.assertEqual(res3[0]["pvlist"]["names"], pvs) with self.assertRaises(RuntimeError) as context: updateconfig(self.conn, self.collection, name, pvlist={"names": pvs0}) self.assertEqual( context.exception.message, "PV collection list exists already, and should not be changed.")
def testRetrieveconfig(self): """""" res = retrieveconfig(self.conn, self.collection, "*", "*") self.assertEqual(len(res), 0, "Should find zero results from an empty database")
def testSaveconfig(self): name = "SR_All_20140421" params = {"desc": "SR daily SCR setpoint without IS kick and septum: SR and RF", "system": "SR", "status": "active", "version": 20140421, } newid = saveconfig(self.conn, self.collection, name, **params) new = retrieveconfig(self.conn, self.collection, name=name) self.assertEqual(len(new), 1, "Should find only one entry instead of %s"%len(new)) self.assertEqual(newid, new[0]["_id"], "Expecting id %s but got %s"%(newid, new[0]["_id"])) with self.assertRaises(ValueError) as context: saveconfig(self.conn, self.collection, name, **params) self.assertEqual(context.exception.message, "Configuration (%s) exists already."%name) name1 = 'SR-All-20140326' params1 = {"desc": "SR daily SCR setpoint: SR and IS PS, RF", "system": "SR", "status": "inactive", "version": 20140326, } newid1 = saveconfig(self.conn, self.collection, name1, **params1) new1 = retrieveconfig(self.conn, self.collection, name=name1) self.assertEqual(len(new1), 1, "Should find only one entry instead of %s"%len(new1)) self.assertEqual(newid1, new1[0]["_id"], "Expecting id %s but got %s"%(newid1, new1[0]["_id"])) self.assertEqual(new1[0]["configidx"]-new[0]["configidx"], 1) name2 = 'SR-All-LTB_PS_"SRC_20131206' params2 = {"desc": "LTB power supply setpoints, for saving/comparing/restoring", "system": "LTB", "status": "active", "version": 20131206, } newid2 = saveconfig(self.conn, self.collection, name2, **params2) new2 = retrieveconfig(self.conn, self.collection, name=name2) self.assertEqual(len(new2), 1, "Should find only one entry instead of %s"%len(new2)) self.assertEqual(newid2, new2[0]["_id"], "Expecting id %s but got %s"%(newid2, new2[0]["_id"])) self.assertEqual(new2[0]["configidx"]-new1[0]["configidx"], 1) name3 = 'LTB_BR_BTS_20140421' params3 = {"desc": "BR SCR PVs with IS kick and septum: LTB, BT, BTS, SR IS", "system": "LTB, BR, BTS", "status": "active", "version": 20140421, } newid3 = saveconfig(self.conn, self.collection, name3, **params3) new3 = retrieveconfig(self.conn, self.collection, name=name3) self.assertEqual(len(new3), 1, "Should find only one entry instead of %s"%len(new3)) self.assertEqual(newid3, new3[0]["_id"], "Expecting id %s but got %s"%(newid3, new3[0]["_id"])) self.assertEqual(new3[0]["configidx"]-new2[0]["configidx"], 1) system4SR = retrieveconfig(self.conn, self.collection, system="SR") self.assertEqual(len(system4SR), 2) system4more = retrieveconfig(self.conn, self.collection, system=params3["system"]) self.assertEqual(len(system4more), 1) system4all = retrieveconfig(self.conn, self.collection, system="*") self.assertEqual(len(system4all), 4) system4all = retrieveconfig(self.conn, self.collection, system="LTB*") self.assertEqual(len(system4all), 2) system4all = retrieveconfig(self.conn, self.collection, system="L*B*") self.assertEqual(len(system4all), 2) system4all = retrieveconfig(self.conn, self.collection, system="L*B,*") self.assertEqual(len(system4all), 1) system4all = retrieveconfig(self.conn, self.collection, system="*S*B,*") self.assertEqual(len(system4all), 0)
def testUpdateconfig(self): """""" name = "SR_All_20140421" params = {"desc": "SR daily SCR setpoint without IS kick and septum: SR and RF", "system": "SR", "status": "active", "version": 20140421, } with self.assertRaises(RuntimeError) as context: updateconfig(self.conn, self.collection, None) self.assertEqual(context.exception.message, "Cannot identify configuration to update.") time.sleep(1) with self.assertRaises(RuntimeError) as context: updateconfig(self.conn, self.collection, name) self.assertEqual(context.exception.message, "Wrong Mongo document for %s" % name) newid = saveconfig(self.conn, self.collection, name, **params) res0 = retrieveconfig(self.conn, self.collection, name) self.assertTrue(updateconfig(self.conn, self.collection, name, status="inactive")) res1 = retrieveconfig(self.conn, self.collection, name) self.assertEqual(newid, res0[0]["_id"]) self.assertEqual(newid, res1[0]["_id"]) self.assertEqual(res0[0]["status"], "active") self.assertEqual(res1[0]["status"], "inactive") self.assertEqual(res1[0]["created_on"], res0[0]["created_on"]) time.sleep(1) # delay required for below updated_on inequality test self.assertTrue(updateconfig(self.conn, self.collection, name, status="active")) res2 = retrieveconfig(self.conn, self.collection, name) self.assertEqual(res2[0]["status"], "active") self.assertNotEqual(res1[0]["updated_on"], res2[0]["updated_on"]) self.assertEqual(res1[0]["created_on"], res2[0]["created_on"]) self.assertEqual(res1[0]["created_on"], res0[0]["created_on"]) pvs = ["RF{Osc:1}Freq:I", "SR-RF{CFC:D}E:Fb-SP", "SR-RF{CFC:D}Phs:Fb-SP", "SR-RF{CFC:D}Tuner:PhaOff-SP", "SR:C01-MG{PS:BT1A}I:Sp1-SP", "SR:C01-MG{PS:BT1A}I:Sp2-SP", "SR:C01-MG{PS:CH1B}I:Sp1-SP", "SR:C01-MG{PS:CH1B}I:Sp2-SP", "SR:C01-MG{PS:CH2B}I:Sp1-SP", "SR:C01-MG{PS:CH2B}I:Sp2-SP", "SR:C01-MG{PS:CL1A}I:Sp1-SP", "SR:C01-MG{PS:CL1A}I:Sp2-SP", "SR:C01-MG{PS:CL2A}I:Sp1-SP", "SR:C01-MG{PS:CL2A}I:Sp2-SP", "SR:C01-MG{PS:CM1A}I:Sp1-SP", "SR:C01-MG{PS:CM1A}I:Sp2-SP", "SR:C01-MG{PS:CM1B}I:Sp1-SP", "SR:C01-MG{PS:CM1B}I:Sp2-SP", "SR:C01-MG{PS:QH1B}I:Sp1-SP", "SR:C01-MG{PS:QH2B}I:Sp1-SP", "SR:C01-MG{PS:QH3B}I:Sp1-SP", "SR:C01-MG{PS:QL1A}I:Sp1-SP", "SR:C01-MG{PS:QL2A}I:Sp1-SP", "SR:C01-MG{PS:QL3A}I:Sp1-SP", "SR:C01-MG{PS:QM1A}I:Sp1-SP", "SR:C01-MG{PS:QM1B}I:Sp1-SP", "SR:C01-MG{PS:QM2A}I:Sp1-SP", "SR:C01-MG{PS:QM2B}I:Sp1-SP", "SR:C01-MG{PS:SH4-P2}I:Sp1-SP", "SR:C01-MG{PS:SM1A-P2}I:Sp1-SP", "SR:C01-MG{PS:SQKM1A}I:Sp1-SP", "SR:C02-MG{PS:BT1A}I:Sp1-SP", "SR:C02-MG{PS:BT1A}I:Sp2-SP", "SR:C02-MG{PS:CH1A}I:Sp1-SP", "SR:C02-MG{PS:CH1A}I:Sp2-SP", "SR:C02-MG{PS:CH2A}I:Sp1-SP", "SR:C02-MG{PS:CH2A}I:Sp2-SP", "SR:C02-MG{PS:CL1B}I:Sp1-SP", "SR:C02-MG{PS:CL1B}I:Sp2-SP", "SR:C02-MG{PS:CL2B}I:Sp1-SP", "SR:C02-MG{PS:CL2B}I:Sp2-SP", "SR:C02-MG{PS:CM1A}I:Sp1-SP", "SR:C02-MG{PS:CM1A}I:Sp2-SP", "SR:C02-MG{PS:CM1B}I:Sp1-SP", "SR:C02-MG{PS:CM1B}I:Sp2-SP", "SR:C02-MG{PS:QH1A}I:Sp1-SP", "SR:C02-MG{PS:QH2A}I:Sp1-SP", "SR:C02-MG{PS:QH3A}I:Sp1-SP", "SR:C02-MG{PS:QL1B}I:Sp1-SP", "SR:C02-MG{PS:QL2B}I:Sp1-SP", "SR:C02-MG{PS:QL3B}I:Sp1-SP", "SR:C02-MG{PS:QM1A}I:Sp1-SP", "SR:C02-MG{PS:QM1B}I:Sp1-SP", "SR:C02-MG{PS:QM2A}I:Sp1-SP", "SR:C02-MG{PS:QM2B}I:Sp1-SP", "SR:C02-MG{PS:SM1B-P2}I:Sp1-SP", "SR:C02-MG{PS:SM2B-P2}I:Sp1-SP", "SR:C02-MG{PS:SQKH1A}I:Sp1-SP", "SR:C03-MG{PS:BT1A}I:Sp1-SP", "SR:C03-MG{PS:BT1A}I:Sp2-SP", "SR:C03-MG{PS:CH1B}I:Sp1-SP", "SR:C03-MG{PS:CH1B}I:Sp2-SP", "SR:C03-MG{PS:CH2B}I:Sp1-SP", "SR:C03-MG{PS:CH2B}I:Sp2-SP", "SR:C03-MG{PS:CL1A}I:Sp1-SP", "SR:C03-MG{PS:CL1A}I:Sp2-SP", "SR:C03-MG{PS:CL2A}I:Sp1-SP", "SR:C03-MG{PS:CL2A}I:Sp2-SP", "SR:C03-MG{PS:CM1A}I:Sp1-SP", "SR:C03-MG{PS:CM1A}I:Sp2-SP", "SR:C03-MG{PS:CM1B}I:Sp1-SP", "SR:C03-MG{PS:CM1B}I:Sp2-SP", "SR:C03-MG{PS:D-SP}I:Sp1-SP", "SR:C03-MG{PS:QH1B}I:Sp1-SP", "SR:C03-MG{PS:QH2B}I:Sp1-SP", "SR:C03-MG{PS:QH3B}I:Sp1-SP", "SR:C03-MG{PS:QL1A}I:Sp1-SP", "SR:C03-MG{PS:QL2A}I:Sp1-SP", "SR:C03-MG{PS:QL3A}I:Sp1-SP", "SR:C03-MG{PS:QM1A}I:Sp1-SP", "SR:C03-MG{PS:QM1B}I:Sp1-SP", "SR:C03-MG{PS:QM2A}I:Sp1-SP", "SR:C03-MG{PS:QM2B}I:Sp1-SP", "SR:C03-MG{PS:SL2-P2}I:Sp1-SP", "SR:C03-MG{PS:SL3-P2}I:Sp1-SP", "SR:C03-MG{PS:SQKM1A}I:Sp1-SP", "SR:C04-MG{PS:BT1A}I:Sp1-SP", "SR:C04-MG{PS:BT1A}I:Sp2-SP", "SR:C04-MG{PS:CH1A}I:Sp1-SP", "SR:C04-MG{PS:CH1A}I:Sp2-SP", "SR:C04-MG{PS:CH2A}I:Sp1-SP", "SR:C04-MG{PS:CH2A}I:Sp2-SP", "SR:C04-MG{PS:CL1B}I:Sp1-SP", "SR:C04-MG{PS:CL1B}I:Sp2-SP", "SR:C04-MG{PS:CL2B}I:Sp1-SP", "SR:C04-MG{PS:CL2B}I:Sp2-SP", "SR:C04-MG{PS:CM1A}I:Sp1-SP", "SR:C04-MG{PS:CM1A}I:Sp2-SP", "SR:C04-MG{PS:CM1B}I:Sp1-SP", "SR:C04-MG{PS:CM1B}I:Sp2-SP", "SR:C04-MG{PS:QH1A}I:Sp1-SP", "SR:C04-MG{PS:QH2A}I:Sp1-SP", "SR:C04-MG{PS:QH3A}I:Sp1-SP", "SR:C04-MG{PS:QL1B}I:Sp1-SP", "SR:C04-MG{PS:QL2B}I:Sp1-SP", "SR:C04-MG{PS:QL3B}I:Sp1-SP", "SR:C04-MG{PS:QM1A}I:Sp1-SP", "SR:C04-MG{PS:QM1B}I:Sp1-SP", "SR:C04-MG{PS:QM2A}I:Sp1-SP", "SR:C04-MG{PS:QM2B}I:Sp1-SP", "SR:C04-MG{PS:SL1-P2}I:Sp1-SP", "SR:C04-MG{PS:SQKH1A}I:Sp1-SP", "SR:C05-MG{PS:BT1A}I:Sp1-SP", "SR:C05-MG{PS:BT1A}I:Sp2-SP", "SR:C05-MG{PS:CH1B}I:Sp1-SP", "SR:C05-MG{PS:CH1B}I:Sp2-SP", "SR:C05-MG{PS:CH2B}I:Sp1-SP", "SR:C05-MG{PS:CH2B}I:Sp2-SP", "SR:C05-MG{PS:CL1A}I:Sp1-SP", "SR:C05-MG{PS:CL1A}I:Sp2-SP", "SR:C05-MG{PS:CL2A}I:Sp1-SP", "SR:C05-MG{PS:CL2A}I:Sp2-SP", "SR:C05-MG{PS:CM1A}I:Sp1-SP", "SR:C05-MG{PS:CM1A}I:Sp2-SP", "SR:C05-MG{PS:CM1B}I:Sp1-SP", "SR:C05-MG{PS:CM1B}I:Sp2-SP", "SR:C05-MG{PS:QH1B}I:Sp1-SP", "SR:C05-MG{PS:QH2B}I:Sp1-SP", "SR:C05-MG{PS:QH3B}I:Sp1-SP", "SR:C05-MG{PS:QL1A}I:Sp1-SP", "SR:C05-MG{PS:QL2A}I:Sp1-SP", "SR:C05-MG{PS:QL3A}I:Sp1-SP", "SR:C05-MG{PS:QM1A}I:Sp1-SP", "SR:C05-MG{PS:QM1B}I:Sp1-SP", "SR:C05-MG{PS:QM2A}I:Sp1-SP", "SR:C05-MG{PS:QM2B}I:Sp1-SP", "SR:C05-MG{PS:SQKM1A}I:Sp1-SP", "SR:C06-MG{PS:BT1A}I:Sp1-SP", "SR:C06-MG{PS:BT1A}I:Sp2-SP", "SR:C06-MG{PS:CH1A}I:Sp1-SP", "SR:C06-MG{PS:CH1A}I:Sp2-SP", "SR:C06-MG{PS:CH2A}I:Sp1-SP", "SR:C06-MG{PS:CH2A}I:Sp2-SP", "SR:C06-MG{PS:CL1B}I:Sp1-SP", "SR:C06-MG{PS:CL1B}I:Sp2-SP", "SR:C06-MG{PS:CL2B}I:Sp1-SP", "SR:C06-MG{PS:CL2B}I:Sp2-SP", "SR:C06-MG{PS:CM1A}I:Sp1-SP", "SR:C06-MG{PS:CM1A}I:Sp2-SP", "SR:C06-MG{PS:CM1B}I:Sp1-SP", "SR:C06-MG{PS:CM1B}I:Sp2-SP", "SR:C06-MG{PS:QH1A}I:Sp1-SP", "SR:C06-MG{PS:QH2A}I:Sp1-SP", "SR:C06-MG{PS:QH3A}I:Sp1-SP", "SR:C06-MG{PS:QL1B}I:Sp1-SP", "SR:C06-MG{PS:QL2B}I:Sp1-SP", "SR:C06-MG{PS:QL3B}I:Sp1-SP", "SR:C06-MG{PS:QM1A}I:Sp1-SP", "SR:C06-MG{PS:QM1B}I:Sp1-SP", "SR:C06-MG{PS:QM2A}I:Sp1-SP", "SR:C06-MG{PS:QM2B}I:Sp1-SP", "SR:C06-MG{PS:SH1-P3}I:Sp1-SP", "SR:C06-MG{PS:SH3-P3}I:Sp1-SP", "SR:C06-MG{PS:SQKH1A}I:Sp1-SP", "SR:C07-MG{PS:BT1A}I:Sp1-SP", "SR:C07-MG{PS:BT1A}I:Sp2-SP", "SR:C07-MG{PS:CH1B}I:Sp1-SP", "SR:C07-MG{PS:CH1B}I:Sp2-SP", "SR:C07-MG{PS:CH2B}I:Sp1-SP", "SR:C07-MG{PS:CH2B}I:Sp2-SP", "SR:C07-MG{PS:CL1A}I:Sp1-SP", "SR:C07-MG{PS:CL1A}I:Sp2-SP", "SR:C07-MG{PS:CL2A}I:Sp1-SP", "SR:C07-MG{PS:CL2A}I:Sp2-SP", "SR:C07-MG{PS:CM1A}I:Sp1-SP", "SR:C07-MG{PS:CM1A}I:Sp2-SP", "SR:C07-MG{PS:CM1B}I:Sp1-SP", "SR:C07-MG{PS:CM1B}I:Sp2-SP", "SR:C07-MG{PS:QH1B}I:Sp1-SP", "SR:C07-MG{PS:QH2B}I:Sp1-SP", "SR:C07-MG{PS:QH3B}I:Sp1-SP", "SR:C07-MG{PS:QL1A}I:Sp1-SP", "SR:C07-MG{PS:QL2A}I:Sp1-SP", "SR:C07-MG{PS:QL3A}I:Sp1-SP", "SR:C07-MG{PS:QM1A}I:Sp1-SP", "SR:C07-MG{PS:QM1B}I:Sp1-SP", "SR:C07-MG{PS:QM2A}I:Sp1-SP", "SR:C07-MG{PS:QM2B}I:Sp1-SP", "SR:C07-MG{PS:SH4-P3}I:Sp1-SP", "SR:C07-MG{PS:SM1A-P3}I:Sp1-SP", "SR:C07-MG{PS:SQKM1A}I:Sp1-SP", "SR:C08-MG{PS:BT1A}I:Sp1-SP", "SR:C08-MG{PS:BT1A}I:Sp2-SP", "SR:C08-MG{PS:CH1A}I:Sp1-SP", "SR:C08-MG{PS:CH1A}I:Sp2-SP", "SR:C08-MG{PS:CH2A}I:Sp1-SP", "SR:C08-MG{PS:CH2A}I:Sp2-SP", "SR:C08-MG{PS:CL1B}I:Sp1-SP", "SR:C08-MG{PS:CL1B}I:Sp2-SP", "SR:C08-MG{PS:CL2B}I:Sp1-SP", "SR:C08-MG{PS:CL2B}I:Sp2-SP", "SR:C08-MG{PS:CM1A}I:Sp1-SP", "SR:C08-MG{PS:CM1A}I:Sp2-SP", "SR:C08-MG{PS:CM1B}I:Sp1-SP", "SR:C08-MG{PS:CM1B}I:Sp2-SP", "SR:C08-MG{PS:QH1A}I:Sp1-SP", "SR:C08-MG{PS:QH2A}I:Sp1-SP", "SR:C08-MG{PS:QH3A}I:Sp1-SP", "SR:C08-MG{PS:QL1B}I:Sp1-SP", "SR:C08-MG{PS:QL2B}I:Sp1-SP", "SR:C08-MG{PS:QL3B}I:Sp1-SP", "SR:C08-MG{PS:QM1A}I:Sp1-SP", "SR:C08-MG{PS:QM1B}I:Sp1-SP", "SR:C08-MG{PS:QM2A}I:Sp1-SP", "SR:C08-MG{PS:QM2B}I:Sp1-SP", "SR:C08-MG{PS:SH1-DW08}I:Sp1-SP", "SR:C08-MG{PS:SH3-DW08}I:Sp1-SP", "SR:C08-MG{PS:SH4-DW08}I:Sp1-SP", "SR:C08-MG{PS:SM1B-P3}I:Sp1-SP", "SR:C08-MG{PS:SM2B-P3}I:Sp1-SP", "SR:C08-MG{PS:SQKH1A}I:Sp1-SP", "SR:C09-MG{PS:BT1A}I:Sp1-SP", "SR:C09-MG{PS:BT1A}I:Sp2-SP", "SR:C09-MG{PS:CH1B}I:Sp1-SP", "SR:C09-MG{PS:CH1B}I:Sp2-SP", "SR:C09-MG{PS:CH2B}I:Sp1-SP", "SR:C09-MG{PS:CH2B}I:Sp2-SP", "SR:C09-MG{PS:CL1A}I:Sp1-SP", "SR:C09-MG{PS:CL1A}I:Sp2-SP", "SR:C09-MG{PS:CL2A}I:Sp1-SP", "SR:C09-MG{PS:CL2A}I:Sp2-SP", "SR:C09-MG{PS:CM1A}I:Sp1-SP", "SR:C09-MG{PS:CM1A}I:Sp2-SP", "SR:C09-MG{PS:CM1B}I:Sp1-SP", "SR:C09-MG{PS:CM1B}I:Sp2-SP", "SR:C09-MG{PS:QH1B}I:Sp1-SP", "SR:C09-MG{PS:QH2B}I:Sp1-SP", "SR:C09-MG{PS:QH3B}I:Sp1-SP", "SR:C09-MG{PS:QL1A}I:Sp1-SP", "SR:C09-MG{PS:QL2A}I:Sp1-SP", "SR:C09-MG{PS:QL3A}I:Sp1-SP", "SR:C09-MG{PS:QM1A}I:Sp1-SP", "SR:C09-MG{PS:QM1B}I:Sp1-SP", "SR:C09-MG{PS:QM2A}I:Sp1-SP", "SR:C09-MG{PS:QM2B}I:Sp1-SP", "SR:C09-MG{PS:SL2-P3}I:Sp1-SP", "SR:C09-MG{PS:SL3-P3}I:Sp1-SP", "SR:C09-MG{PS:SQKM1A}I:Sp1-SP", "SR:C10-MG{PS:BT1A}I:Sp1-SP", "SR:C10-MG{PS:BT1A}I:Sp2-SP", "SR:C10-MG{PS:CH1A}I:Sp1-SP", "SR:C10-MG{PS:CH1A}I:Sp2-SP", "SR:C10-MG{PS:CH2A}I:Sp1-SP", "SR:C10-MG{PS:CH2A}I:Sp2-SP", "SR:C10-MG{PS:CL1B}I:Sp1-SP", "SR:C10-MG{PS:CL1B}I:Sp2-SP", "SR:C10-MG{PS:CL2B}I:Sp1-SP", "SR:C10-MG{PS:CL2B}I:Sp2-SP", "SR:C10-MG{PS:CM1A}I:Sp1-SP", "SR:C10-MG{PS:CM1A}I:Sp2-SP", "SR:C10-MG{PS:CM1B}I:Sp1-SP", "SR:C10-MG{PS:CM1B}I:Sp2-SP", "SR:C10-MG{PS:QH1A}I:Sp1-SP", "SR:C10-MG{PS:QH2A}I:Sp1-SP", "SR:C10-MG{PS:QH3A}I:Sp1-SP", "SR:C10-MG{PS:QL1B}I:Sp1-SP", "SR:C10-MG{PS:QL2B}I:Sp1-SP", "SR:C10-MG{PS:QL3B}I:Sp1-SP", "SR:C10-MG{PS:QM1A}I:Sp1-SP", "SR:C10-MG{PS:QM1B}I:Sp1-SP", "SR:C10-MG{PS:QM2A}I:Sp1-SP", "SR:C10-MG{PS:QM2B}I:Sp1-SP", "SR:C10-MG{PS:SL1-P3}I:Sp1-SP", "SR:C10-MG{PS:SQKH1A}I:Sp1-SP", "SR:C11-MG{PS:BT1A}I:Sp1-SP", "SR:C11-MG{PS:BT1A}I:Sp2-SP", "SR:C11-MG{PS:CH1B}I:Sp1-SP", "SR:C11-MG{PS:CH1B}I:Sp2-SP", "SR:C11-MG{PS:CH2B}I:Sp1-SP", "SR:C11-MG{PS:CH2B}I:Sp2-SP", "SR:C11-MG{PS:CL1A}I:Sp1-SP", "SR:C11-MG{PS:CL1A}I:Sp2-SP", "SR:C11-MG{PS:CL2A}I:Sp1-SP", "SR:C11-MG{PS:CL2A}I:Sp2-SP", "SR:C11-MG{PS:CM1A}I:Sp1-SP", "SR:C11-MG{PS:CM1A}I:Sp2-SP", "SR:C11-MG{PS:CM1B}I:Sp1-SP", "SR:C11-MG{PS:CM1B}I:Sp2-SP", "SR:C11-MG{PS:QH1B}I:Sp1-SP", "SR:C11-MG{PS:QH2B}I:Sp1-SP", "SR:C11-MG{PS:QH3B}I:Sp1-SP", "SR:C11-MG{PS:QL1A}I:Sp1-SP", "SR:C11-MG{PS:QL2A}I:Sp1-SP", "SR:C11-MG{PS:QL3A}I:Sp1-SP", "SR:C11-MG{PS:QM1A}I:Sp1-SP", "SR:C11-MG{PS:QM1B}I:Sp1-SP", "SR:C11-MG{PS:QM2A}I:Sp1-SP", "SR:C11-MG{PS:QM2B}I:Sp1-SP", "SR:C11-MG{PS:SQKM1A}I:Sp1-SP", "SR:C12-MG{PS:BT1A}I:Sp1-SP", "SR:C12-MG{PS:BT1A}I:Sp2-SP", "SR:C12-MG{PS:CH1A}I:Sp1-SP", "SR:C12-MG{PS:CH1A}I:Sp2-SP", "SR:C12-MG{PS:CH2A}I:Sp1-SP", "SR:C12-MG{PS:CH2A}I:Sp2-SP", "SR:C12-MG{PS:CL1B}I:Sp1-SP", "SR:C12-MG{PS:CL1B}I:Sp2-SP", "SR:C12-MG{PS:CL2B}I:Sp1-SP", "SR:C12-MG{PS:CL2B}I:Sp2-SP", "SR:C12-MG{PS:CM1A}I:Sp1-SP", "SR:C12-MG{PS:CM1A}I:Sp2-SP", "SR:C12-MG{PS:CM1B}I:Sp1-SP", "SR:C12-MG{PS:CM1B}I:Sp2-SP", "SR:C12-MG{PS:QH1A}I:Sp1-SP", "SR:C12-MG{PS:QH2A}I:Sp1-SP", "SR:C12-MG{PS:QH3A}I:Sp1-SP", "SR:C12-MG{PS:QL1B}I:Sp1-SP", "SR:C12-MG{PS:QL2B}I:Sp1-SP", "SR:C12-MG{PS:QL3B}I:Sp1-SP", "SR:C12-MG{PS:QM1A}I:Sp1-SP", "SR:C12-MG{PS:QM1B}I:Sp1-SP", "SR:C12-MG{PS:QM2A}I:Sp1-SP", "SR:C12-MG{PS:QM2B}I:Sp1-SP", "SR:C12-MG{PS:SH1-P4}I:Sp1-SP", "SR:C12-MG{PS:SH3-P4}I:Sp1-SP", "SR:C12-MG{PS:SQKH1A}I:Sp1-SP", "SR:C13-MG{PS:BT1A}I:Sp1-SP", "SR:C13-MG{PS:BT1A}I:Sp2-SP", "SR:C13-MG{PS:CH1B}I:Sp1-SP", "SR:C13-MG{PS:CH1B}I:Sp2-SP", "SR:C13-MG{PS:CH2B}I:Sp1-SP", "SR:C13-MG{PS:CH2B}I:Sp2-SP", "SR:C13-MG{PS:CL1A}I:Sp1-SP", "SR:C13-MG{PS:CL1A}I:Sp2-SP", "SR:C13-MG{PS:CL2A}I:Sp1-SP", "SR:C13-MG{PS:CL2A}I:Sp2-SP", "SR:C13-MG{PS:CM1A}I:Sp1-SP", "SR:C13-MG{PS:CM1A}I:Sp2-SP", "SR:C13-MG{PS:CM1B}I:Sp1-SP", "SR:C13-MG{PS:CM1B}I:Sp2-SP", "SR:C13-MG{PS:QH1B}I:Sp1-SP", "SR:C13-MG{PS:QH2B}I:Sp1-SP", "SR:C13-MG{PS:QH3B}I:Sp1-SP", "SR:C13-MG{PS:QL1A}I:Sp1-SP", "SR:C13-MG{PS:QL2A}I:Sp1-SP", "SR:C13-MG{PS:QL3A}I:Sp1-SP", "SR:C13-MG{PS:QM1A}I:Sp1-SP", "SR:C13-MG{PS:QM1B}I:Sp1-SP", "SR:C13-MG{PS:QM2A}I:Sp1-SP", "SR:C13-MG{PS:QM2B}I:Sp1-SP", "SR:C13-MG{PS:SH4-P4}I:Sp1-SP", "SR:C13-MG{PS:SM1A-P4}I:Sp1-SP", "SR:C13-MG{PS:SQKM1A}I:Sp1-SP", "SR:C14-MG{PS:BT1A}I:Sp1-SP", "SR:C14-MG{PS:BT1A}I:Sp2-SP", "SR:C14-MG{PS:CH1A}I:Sp1-SP", "SR:C14-MG{PS:CH1A}I:Sp2-SP", "SR:C14-MG{PS:CH2A}I:Sp1-SP", "SR:C14-MG{PS:CH2A}I:Sp2-SP", "SR:C14-MG{PS:CL1B}I:Sp1-SP", "SR:C14-MG{PS:CL1B}I:Sp2-SP", "SR:C14-MG{PS:CL2B}I:Sp1-SP", "SR:C14-MG{PS:CL2B}I:Sp2-SP", "SR:C14-MG{PS:CM1A}I:Sp1-SP", "SR:C14-MG{PS:CM1A}I:Sp2-SP", "SR:C14-MG{PS:CM1B}I:Sp1-SP", "SR:C14-MG{PS:CM1B}I:Sp2-SP", "SR:C14-MG{PS:QH1A}I:Sp1-SP", "SR:C14-MG{PS:QH2A}I:Sp1-SP", "SR:C14-MG{PS:QH3A}I:Sp1-SP", "SR:C14-MG{PS:QL1B}I:Sp1-SP", "SR:C14-MG{PS:QL2B}I:Sp1-SP", "SR:C14-MG{PS:QL3B}I:Sp1-SP", "SR:C14-MG{PS:QM1A}I:Sp1-SP", "SR:C14-MG{PS:QM1B}I:Sp1-SP", "SR:C14-MG{PS:QM2A}I:Sp1-SP", "SR:C14-MG{PS:QM2B}I:Sp1-SP", "SR:C14-MG{PS:SM1B-P4}I:Sp1-SP", "SR:C14-MG{PS:SM2B-P4}I:Sp1-SP", "SR:C14-MG{PS:SQKH1A}I:Sp1-SP", "SR:C15-MG{PS:BT1A}I:Sp1-SP", "SR:C15-MG{PS:BT1A}I:Sp2-SP", "SR:C15-MG{PS:CH1B}I:Sp1-SP", "SR:C15-MG{PS:CH1B}I:Sp2-SP", "SR:C15-MG{PS:CH2B}I:Sp1-SP", "SR:C15-MG{PS:CH2B}I:Sp2-SP", "SR:C15-MG{PS:CL1A}I:Sp1-SP", "SR:C15-MG{PS:CL1A}I:Sp2-SP", "SR:C15-MG{PS:CL2A}I:Sp1-SP", "SR:C15-MG{PS:CL2A}I:Sp2-SP", "SR:C15-MG{PS:CM1A}I:Sp1-SP", "SR:C15-MG{PS:CM1A}I:Sp2-SP", "SR:C15-MG{PS:CM1B}I:Sp1-SP", "SR:C15-MG{PS:CM1B}I:Sp2-SP", "SR:C15-MG{PS:QH1B}I:Sp1-SP", "SR:C15-MG{PS:QH2B}I:Sp1-SP", "SR:C15-MG{PS:QH3B}I:Sp1-SP", "SR:C15-MG{PS:QL1A}I:Sp1-SP", "SR:C15-MG{PS:QL2A}I:Sp1-SP", "SR:C15-MG{PS:QL3A}I:Sp1-SP", "SR:C15-MG{PS:QM1A}I:Sp1-SP", "SR:C15-MG{PS:QM1B}I:Sp1-SP", "SR:C15-MG{PS:QM2A}I:Sp1-SP", "SR:C15-MG{PS:QM2B}I:Sp1-SP", "SR:C15-MG{PS:SL2-P4}I:Sp1-SP", "SR:C15-MG{PS:SL3-P4}I:Sp1-SP", "SR:C15-MG{PS:SQKM1A}I:Sp1-SP", "SR:C16-MG{PS:BT1A}I:Sp1-SP", "SR:C16-MG{PS:BT1A}I:Sp2-SP", "SR:C16-MG{PS:CH1A}I:Sp1-SP", "SR:C16-MG{PS:CH1A}I:Sp2-SP", "SR:C16-MG{PS:CH2A}I:Sp1-SP", "SR:C16-MG{PS:CH2A}I:Sp2-SP", "SR:C16-MG{PS:CL1B}I:Sp1-SP", "SR:C16-MG{PS:CL1B}I:Sp2-SP", "SR:C16-MG{PS:CL2B}I:Sp1-SP", "SR:C16-MG{PS:CL2B}I:Sp2-SP", "SR:C16-MG{PS:CM1A}I:Sp1-SP", "SR:C16-MG{PS:CM1A}I:Sp2-SP", "SR:C16-MG{PS:CM1B}I:Sp1-SP", "SR:C16-MG{PS:CM1B}I:Sp2-SP", "SR:C16-MG{PS:QH1A}I:Sp1-SP", "SR:C16-MG{PS:QH2A}I:Sp1-SP", "SR:C16-MG{PS:QH3A}I:Sp1-SP", "SR:C16-MG{PS:QL1B}I:Sp1-SP", "SR:C16-MG{PS:QL2B}I:Sp1-SP", "SR:C16-MG{PS:QL3B}I:Sp1-SP", "SR:C16-MG{PS:QM1A}I:Sp1-SP", "SR:C16-MG{PS:QM1B}I:Sp1-SP", "SR:C16-MG{PS:QM2A}I:Sp1-SP", "SR:C16-MG{PS:QM2B}I:Sp1-SP", "SR:C16-MG{PS:SL1-P4}I:Sp1-SP", "SR:C16-MG{PS:SQKH1A}I:Sp1-SP", "SR:C17-MG{PS:BT1A}I:Sp1-SP", "SR:C17-MG{PS:BT1A}I:Sp2-SP", "SR:C17-MG{PS:CH1B}I:Sp1-SP", "SR:C17-MG{PS:CH1B}I:Sp2-SP", "SR:C17-MG{PS:CH2B}I:Sp1-SP", "SR:C17-MG{PS:CH2B}I:Sp2-SP", "SR:C17-MG{PS:CL1A}I:Sp1-SP", "SR:C17-MG{PS:CL1A}I:Sp2-SP", "SR:C17-MG{PS:CL2A}I:Sp1-SP", "SR:C17-MG{PS:CL2A}I:Sp2-SP", "SR:C17-MG{PS:CM1A}I:Sp1-SP", "SR:C17-MG{PS:CM1A}I:Sp2-SP", "SR:C17-MG{PS:CM1B}I:Sp1-SP", "SR:C17-MG{PS:CM1B}I:Sp2-SP", "SR:C17-MG{PS:QH1B}I:Sp1-SP", "SR:C17-MG{PS:QH2B}I:Sp1-SP", "SR:C17-MG{PS:QH3B}I:Sp1-SP", "SR:C17-MG{PS:QL1A}I:Sp1-SP", "SR:C17-MG{PS:QL2A}I:Sp1-SP", "SR:C17-MG{PS:QL3A}I:Sp1-SP", "SR:C17-MG{PS:QM1A}I:Sp1-SP", "SR:C17-MG{PS:QM1B}I:Sp1-SP", "SR:C17-MG{PS:QM2A}I:Sp1-SP", "SR:C17-MG{PS:QM2B}I:Sp1-SP", "SR:C17-MG{PS:SQKM1A}I:Sp1-SP", "SR:C18-MG{PS:BT1A}I:Sp1-SP", "SR:C18-MG{PS:BT1A}I:Sp2-SP", "SR:C18-MG{PS:CH1A}I:Sp1-SP", "SR:C18-MG{PS:CH1A}I:Sp2-SP", "SR:C18-MG{PS:CH2A}I:Sp1-SP", "SR:C18-MG{PS:CH2A}I:Sp2-SP", "SR:C18-MG{PS:CL1B}I:Sp1-SP", "SR:C18-MG{PS:CL1B}I:Sp2-SP", "SR:C18-MG{PS:CL2B}I:Sp1-SP", "SR:C18-MG{PS:CL2B}I:Sp2-SP", "SR:C18-MG{PS:CM1A}I:Sp1-SP", "SR:C18-MG{PS:CM1A}I:Sp2-SP", "SR:C18-MG{PS:CM1B}I:Sp1-SP", "SR:C18-MG{PS:CM1B}I:Sp2-SP", "SR:C18-MG{PS:QH1A}I:Sp1-SP", "SR:C18-MG{PS:QH2A}I:Sp1-SP", "SR:C18-MG{PS:QH3A}I:Sp1-SP", "SR:C18-MG{PS:QL1B}I:Sp1-SP", "SR:C18-MG{PS:QL2B}I:Sp1-SP", "SR:C18-MG{PS:QL3B}I:Sp1-SP", "SR:C18-MG{PS:QM1A}I:Sp1-SP", "SR:C18-MG{PS:QM1B}I:Sp1-SP", "SR:C18-MG{PS:QM2A}I:Sp1-SP", "SR:C18-MG{PS:QM2B}I:Sp1-SP", "SR:C18-MG{PS:SH1-DW18}I:Sp1-SP", "SR:C18-MG{PS:SH1-P5}I:Sp1-SP", "SR:C18-MG{PS:SH3-DW18}I:Sp1-SP", "SR:C18-MG{PS:SH3-P5}I:Sp1-SP", "SR:C18-MG{PS:SH4-DW18}I:Sp1-SP", "SR:C18-MG{PS:SQKH1A}I:Sp1-SP", "SR:C19-MG{PS:BT1A}I:Sp1-SP", "SR:C19-MG{PS:BT1A}I:Sp2-SP", "SR:C19-MG{PS:CH1B}I:Sp1-SP", "SR:C19-MG{PS:CH1B}I:Sp2-SP", "SR:C19-MG{PS:CH2B}I:Sp1-SP", "SR:C19-MG{PS:CH2B}I:Sp2-SP", "SR:C19-MG{PS:CL1A}I:Sp1-SP", "SR:C19-MG{PS:CL1A}I:Sp2-SP", "SR:C19-MG{PS:CL2A}I:Sp1-SP", "SR:C19-MG{PS:CL2A}I:Sp2-SP", "SR:C19-MG{PS:CM1A}I:Sp1-SP", "SR:C19-MG{PS:CM1A}I:Sp2-SP", "SR:C19-MG{PS:CM1B}I:Sp1-SP", "SR:C19-MG{PS:CM1B}I:Sp2-SP", "SR:C19-MG{PS:QH1B}I:Sp1-SP", "SR:C19-MG{PS:QH2B}I:Sp1-SP", "SR:C19-MG{PS:QH3B}I:Sp1-SP", "SR:C19-MG{PS:QL1A}I:Sp1-SP", "SR:C19-MG{PS:QL2A}I:Sp1-SP", "SR:C19-MG{PS:QL3A}I:Sp1-SP", "SR:C19-MG{PS:QM1A}I:Sp1-SP", "SR:C19-MG{PS:QM1B}I:Sp1-SP", "SR:C19-MG{PS:QM2A}I:Sp1-SP", "SR:C19-MG{PS:QM2B}I:Sp1-SP", "SR:C19-MG{PS:SH4-P5}I:Sp1-SP", "SR:C19-MG{PS:SM1A-P5}I:Sp1-SP", "SR:C19-MG{PS:SQKM1A}I:Sp1-SP", "SR:C20-MG{PS:BT1A}I:Sp1-SP", "SR:C20-MG{PS:BT1A}I:Sp2-SP", "SR:C20-MG{PS:CH1A}I:Sp1-SP", "SR:C20-MG{PS:CH1A}I:Sp2-SP", "SR:C20-MG{PS:CH2A}I:Sp1-SP", "SR:C20-MG{PS:CH2A}I:Sp2-SP", "SR:C20-MG{PS:CL1B}I:Sp1-SP", "SR:C20-MG{PS:CL1B}I:Sp2-SP", "SR:C20-MG{PS:CL2B}I:Sp1-SP", "SR:C20-MG{PS:CL2B}I:Sp2-SP", "SR:C20-MG{PS:CM1A}I:Sp1-SP", "SR:C20-MG{PS:CM1A}I:Sp2-SP", "SR:C20-MG{PS:CM1B}I:Sp1-SP", "SR:C20-MG{PS:CM1B}I:Sp2-SP", "SR:C20-MG{PS:QH1A}I:Sp1-SP", "SR:C20-MG{PS:QH2A}I:Sp1-SP", "SR:C20-MG{PS:QH3A}I:Sp1-SP", "SR:C20-MG{PS:QL1B}I:Sp1-SP", "SR:C20-MG{PS:QL2B}I:Sp1-SP", "SR:C20-MG{PS:QL3B}I:Sp1-SP", "SR:C20-MG{PS:QM1A}I:Sp1-SP", "SR:C20-MG{PS:QM1B}I:Sp1-SP", "SR:C20-MG{PS:QM2A}I:Sp1-SP", "SR:C20-MG{PS:QM2B}I:Sp1-SP", "SR:C20-MG{PS:SM1B-P5}I:Sp1-SP", "SR:C20-MG{PS:SM2B-P5}I:Sp1-SP", "SR:C20-MG{PS:SQKH1A}I:Sp1-SP", "SR:C21-MG{PS:BT1A}I:Sp1-SP", "SR:C21-MG{PS:BT1A}I:Sp2-SP", "SR:C21-MG{PS:CH1B}I:Sp1-SP", "SR:C21-MG{PS:CH1B}I:Sp2-SP", "SR:C21-MG{PS:CH2B}I:Sp1-SP", "SR:C21-MG{PS:CH2B}I:Sp2-SP", "SR:C21-MG{PS:CL1A}I:Sp1-SP", "SR:C21-MG{PS:CL1A}I:Sp2-SP", "SR:C21-MG{PS:CL2A}I:Sp1-SP", "SR:C21-MG{PS:CL2A}I:Sp2-SP", "SR:C21-MG{PS:CM1A}I:Sp1-SP", "SR:C21-MG{PS:CM1A}I:Sp2-SP", "SR:C21-MG{PS:CM1B}I:Sp1-SP", "SR:C21-MG{PS:CM1B}I:Sp2-SP", "SR:C21-MG{PS:QH1B}I:Sp1-SP", "SR:C21-MG{PS:QH2B}I:Sp1-SP", "SR:C21-MG{PS:QH3B}I:Sp1-SP", "SR:C21-MG{PS:QL1A}I:Sp1-SP", "SR:C21-MG{PS:QL2A}I:Sp1-SP", "SR:C21-MG{PS:QL3A}I:Sp1-SP", "SR:C21-MG{PS:QM1A}I:Sp1-SP", "SR:C21-MG{PS:QM1B}I:Sp1-SP", "SR:C21-MG{PS:QM2A}I:Sp1-SP", "SR:C21-MG{PS:QM2B}I:Sp1-SP", "SR:C21-MG{PS:SL2-P5}I:Sp1-SP", "SR:C21-MG{PS:SL3-P5}I:Sp1-SP", "SR:C21-MG{PS:SQKM1A}I:Sp1-SP", "SR:C22-MG{PS:BT1A}I:Sp1-SP", "SR:C22-MG{PS:BT1A}I:Sp2-SP", "SR:C22-MG{PS:CH1A}I:Sp1-SP", "SR:C22-MG{PS:CH1A}I:Sp2-SP", "SR:C22-MG{PS:CH2A}I:Sp1-SP", "SR:C22-MG{PS:CH2A}I:Sp2-SP", "SR:C22-MG{PS:CL1B}I:Sp1-SP", "SR:C22-MG{PS:CL1B}I:Sp2-SP", "SR:C22-MG{PS:CL2B}I:Sp1-SP", "SR:C22-MG{PS:CL2B}I:Sp2-SP", "SR:C22-MG{PS:CM1A}I:Sp1-SP", "SR:C22-MG{PS:CM1A}I:Sp2-SP", "SR:C22-MG{PS:CM1B}I:Sp1-SP", "SR:C22-MG{PS:CM1B}I:Sp2-SP", "SR:C22-MG{PS:QH1A}I:Sp1-SP", "SR:C22-MG{PS:QH2A}I:Sp1-SP", "SR:C22-MG{PS:QH3A}I:Sp1-SP", "SR:C22-MG{PS:QL1B}I:Sp1-SP", "SR:C22-MG{PS:QL2B}I:Sp1-SP", "SR:C22-MG{PS:QL3B}I:Sp1-SP", "SR:C22-MG{PS:QM1A}I:Sp1-SP", "SR:C22-MG{PS:QM1B}I:Sp1-SP", "SR:C22-MG{PS:QM2A}I:Sp1-SP", "SR:C22-MG{PS:QM2B}I:Sp1-SP", "SR:C22-MG{PS:SL1-P5}I:Sp1-SP", "SR:C22-MG{PS:SQKH1A}I:Sp1-SP", "SR:C23-MG{PS:BT1A}I:Sp1-SP", "SR:C23-MG{PS:BT1A}I:Sp2-SP", "SR:C23-MG{PS:CH1B}I:Sp1-SP", "SR:C23-MG{PS:CH1B}I:Sp2-SP", "SR:C23-MG{PS:CH2B}I:Sp1-SP", "SR:C23-MG{PS:CH2B}I:Sp2-SP", "SR:C23-MG{PS:CL1A}I:Sp1-SP", "SR:C23-MG{PS:CL1A}I:Sp2-SP", "SR:C23-MG{PS:CL2A}I:Sp1-SP", "SR:C23-MG{PS:CL2A}I:Sp2-SP", "SR:C23-MG{PS:CM1A}I:Sp1-SP", "SR:C23-MG{PS:CM1A}I:Sp2-SP", "SR:C23-MG{PS:CM1B}I:Sp1-SP", "SR:C23-MG{PS:CM1B}I:Sp2-SP", "SR:C23-MG{PS:QH1B}I:Sp1-SP", "SR:C23-MG{PS:QH2B}I:Sp1-SP", "SR:C23-MG{PS:QH3B}I:Sp1-SP", "SR:C23-MG{PS:QL1A}I:Sp1-SP", "SR:C23-MG{PS:QL2A}I:Sp1-SP", "SR:C23-MG{PS:QL3A}I:Sp1-SP", "SR:C23-MG{PS:QM1A}I:Sp1-SP", "SR:C23-MG{PS:QM1B}I:Sp1-SP", "SR:C23-MG{PS:QM2A}I:Sp1-SP", "SR:C23-MG{PS:QM2B}I:Sp1-SP", "SR:C23-MG{PS:SQKM1A}I:Sp1-SP", "SR:C24-MG{PS:BT1A}I:Sp1-SP", "SR:C24-MG{PS:BT1A}I:Sp2-SP", "SR:C24-MG{PS:CH1A}I:Sp1-SP", "SR:C24-MG{PS:CH1A}I:Sp2-SP", "SR:C24-MG{PS:CH2A}I:Sp1-SP", "SR:C24-MG{PS:CH2A}I:Sp2-SP", "SR:C24-MG{PS:CL1B}I:Sp1-SP", "SR:C24-MG{PS:CL1B}I:Sp2-SP", "SR:C24-MG{PS:CL2B}I:Sp1-SP", "SR:C24-MG{PS:CL2B}I:Sp2-SP", "SR:C24-MG{PS:CM1A}I:Sp1-SP", "SR:C24-MG{PS:CM1A}I:Sp2-SP", "SR:C24-MG{PS:CM1B}I:Sp1-SP", "SR:C24-MG{PS:CM1B}I:Sp2-SP", "SR:C24-MG{PS:QH1A}I:Sp1-SP", "SR:C24-MG{PS:QH2A}I:Sp1-SP", "SR:C24-MG{PS:QH3A}I:Sp1-SP", "SR:C24-MG{PS:QL1B}I:Sp1-SP", "SR:C24-MG{PS:QL2B}I:Sp1-SP", "SR:C24-MG{PS:QL3B}I:Sp1-SP", "SR:C24-MG{PS:QM1A}I:Sp1-SP", "SR:C24-MG{PS:QM1B}I:Sp1-SP", "SR:C24-MG{PS:QM2A}I:Sp1-SP", "SR:C24-MG{PS:QM2B}I:Sp1-SP", "SR:C24-MG{PS:SH1-P1}I:Sp1-SP", "SR:C24-MG{PS:SH3-P1}I:Sp1-SP", "SR:C24-MG{PS:SQKH1A}I:Sp1-SP", "SR:C25-MG{PS:BT1A}I:Sp1-SP", "SR:C25-MG{PS:BT1A}I:Sp2-SP", "SR:C25-MG{PS:CH1B}I:Sp1-SP", "SR:C25-MG{PS:CH1B}I:Sp2-SP", "SR:C25-MG{PS:CH2B}I:Sp1-SP", "SR:C25-MG{PS:CH2B}I:Sp2-SP", "SR:C25-MG{PS:CL1A}I:Sp1-SP", "SR:C25-MG{PS:CL1A}I:Sp2-SP", "SR:C25-MG{PS:CL2A}I:Sp1-SP", "SR:C25-MG{PS:CL2A}I:Sp2-SP", "SR:C25-MG{PS:CM1A}I:Sp1-SP", "SR:C25-MG{PS:CM1A}I:Sp2-SP", "SR:C25-MG{PS:CM1B}I:Sp1-SP", "SR:C25-MG{PS:CM1B}I:Sp2-SP", "SR:C25-MG{PS:QH1B}I:Sp1-SP", "SR:C25-MG{PS:QH2B}I:Sp1-SP", "SR:C25-MG{PS:QH3B}I:Sp1-SP", "SR:C25-MG{PS:QL1A}I:Sp1-SP", "SR:C25-MG{PS:QL2A}I:Sp1-SP", "SR:C25-MG{PS:QL3A}I:Sp1-SP", "SR:C25-MG{PS:QM1A}I:Sp1-SP", "SR:C25-MG{PS:QM1B}I:Sp1-SP", "SR:C25-MG{PS:QM2A}I:Sp1-SP", "SR:C25-MG{PS:QM2B}I:Sp1-SP", "SR:C25-MG{PS:SH4-P1}I:Sp1-SP", "SR:C25-MG{PS:SM1A-P1}I:Sp1-SP", "SR:C25-MG{PS:SQKM1A}I:Sp1-SP", "SR:C26-MG{PS:BT1A}I:Sp1-SP", "SR:C26-MG{PS:BT1A}I:Sp2-SP", "SR:C26-MG{PS:CH1A}I:Sp1-SP", "SR:C26-MG{PS:CH1A}I:Sp2-SP", "SR:C26-MG{PS:CH2A}I:Sp1-SP", "SR:C26-MG{PS:CH2A}I:Sp2-SP", "SR:C26-MG{PS:CL1B}I:Sp1-SP", "SR:C26-MG{PS:CL1B}I:Sp2-SP", "SR:C26-MG{PS:CL2B}I:Sp1-SP", "SR:C26-MG{PS:CL2B}I:Sp2-SP", "SR:C26-MG{PS:CM1A}I:Sp1-SP", "SR:C26-MG{PS:CM1A}I:Sp2-SP", "SR:C26-MG{PS:CM1B}I:Sp1-SP", "SR:C26-MG{PS:CM1B}I:Sp2-SP", "SR:C26-MG{PS:QH1A}I:Sp1-SP", "SR:C26-MG{PS:QH2A}I:Sp1-SP", "SR:C26-MG{PS:QH3A}I:Sp1-SP", "SR:C26-MG{PS:QL1B}I:Sp1-SP", "SR:C26-MG{PS:QL2B}I:Sp1-SP", "SR:C26-MG{PS:QL3B}I:Sp1-SP", "SR:C26-MG{PS:QM1A}I:Sp1-SP", "SR:C26-MG{PS:QM1B}I:Sp1-SP", "SR:C26-MG{PS:QM2A}I:Sp1-SP", "SR:C26-MG{PS:QM2B}I:Sp1-SP", "SR:C26-MG{PS:SM1B-P1}I:Sp1-SP", "SR:C26-MG{PS:SM2B-P1}I:Sp1-SP", "SR:C26-MG{PS:SQKH1A}I:Sp1-SP", "SR:C27-MG{PS:BT1A}I:Sp1-SP", "SR:C27-MG{PS:BT1A}I:Sp2-SP", "SR:C27-MG{PS:CH1B}I:Sp1-SP", "SR:C27-MG{PS:CH1B}I:Sp2-SP", "SR:C27-MG{PS:CH2B}I:Sp1-SP", "SR:C27-MG{PS:CH2B}I:Sp2-SP", "SR:C27-MG{PS:CL1A}I:Sp1-SP", "SR:C27-MG{PS:CL1A}I:Sp2-SP", "SR:C27-MG{PS:CL2A}I:Sp1-SP", "SR:C27-MG{PS:CL2A}I:Sp2-SP", "SR:C27-MG{PS:CM1A}I:Sp1-SP", "SR:C27-MG{PS:CM1A}I:Sp2-SP", "SR:C27-MG{PS:CM1B}I:Sp1-SP", "SR:C27-MG{PS:CM1B}I:Sp2-SP", "SR:C27-MG{PS:QH1B}I:Sp1-SP", "SR:C27-MG{PS:QH2B}I:Sp1-SP", "SR:C27-MG{PS:QH3B}I:Sp1-SP", "SR:C27-MG{PS:QL1A}I:Sp1-SP", "SR:C27-MG{PS:QL2A}I:Sp1-SP", "SR:C27-MG{PS:QL3A}I:Sp1-SP", "SR:C27-MG{PS:QM1A}I:Sp1-SP", "SR:C27-MG{PS:QM1B}I:Sp1-SP", "SR:C27-MG{PS:QM2A}I:Sp1-SP", "SR:C27-MG{PS:QM2B}I:Sp1-SP", "SR:C27-MG{PS:SL2-P1}I:Sp1-SP", "SR:C27-MG{PS:SL3-P1}I:Sp1-SP", "SR:C27-MG{PS:SQKM1A}I:Sp1-SP", "SR:C28-MG{PS:BT1A}I:Sp1-SP", "SR:C28-MG{PS:BT1A}I:Sp2-SP", "SR:C28-MG{PS:CH1A}I:Sp1-SP", "SR:C28-MG{PS:CH1A}I:Sp2-SP", "SR:C28-MG{PS:CH2A}I:Sp1-SP", "SR:C28-MG{PS:CH2A}I:Sp2-SP", "SR:C28-MG{PS:CL1B}I:Sp1-SP", "SR:C28-MG{PS:CL1B}I:Sp2-SP", "SR:C28-MG{PS:CL2B}I:Sp1-SP", "SR:C28-MG{PS:CL2B}I:Sp2-SP", "SR:C28-MG{PS:CM1A}I:Sp1-SP", "SR:C28-MG{PS:CM1A}I:Sp2-SP", "SR:C28-MG{PS:CM1B}I:Sp1-SP", "SR:C28-MG{PS:CM1B}I:Sp2-SP", "SR:C28-MG{PS:QH1A}I:Sp1-SP", "SR:C28-MG{PS:QH2A}I:Sp1-SP", "SR:C28-MG{PS:QH3A}I:Sp1-SP", "SR:C28-MG{PS:QL1B}I:Sp1-SP", "SR:C28-MG{PS:QL2B}I:Sp1-SP", "SR:C28-MG{PS:QL3B}I:Sp1-SP", "SR:C28-MG{PS:QM1A}I:Sp1-SP", "SR:C28-MG{PS:QM1B}I:Sp1-SP", "SR:C28-MG{PS:QM2A}I:Sp1-SP", "SR:C28-MG{PS:QM2B}I:Sp1-SP", "SR:C28-MG{PS:SH1-DW28}I:Sp1-SP", "SR:C28-MG{PS:SH3-DW28}I:Sp1-SP", "SR:C28-MG{PS:SH4-DW28}I:Sp1-SP", "SR:C28-MG{PS:SL1-P1}I:Sp1-SP", "SR:C28-MG{PS:SQKH1A}I:Sp1-SP", "SR:C29-MG{PS:BT1A}I:Sp1-SP", "SR:C29-MG{PS:BT1A}I:Sp2-SP", "SR:C29-MG{PS:CH1B}I:Sp1-SP", "SR:C29-MG{PS:CH1B}I:Sp2-SP", "SR:C29-MG{PS:CH2B}I:Sp1-SP", "SR:C29-MG{PS:CH2B}I:Sp2-SP", "SR:C29-MG{PS:CL1A}I:Sp1-SP", "SR:C29-MG{PS:CL1A}I:Sp2-SP", "SR:C29-MG{PS:CL2A}I:Sp1-SP", "SR:C29-MG{PS:CL2A}I:Sp2-SP", "SR:C29-MG{PS:CM1A}I:Sp1-SP", "SR:C29-MG{PS:CM1A}I:Sp2-SP", "SR:C29-MG{PS:CM1B}I:Sp1-SP", "SR:C29-MG{PS:CM1B}I:Sp2-SP", "SR:C29-MG{PS:QH1B}I:Sp1-SP", "SR:C29-MG{PS:QH2B}I:Sp1-SP", "SR:C29-MG{PS:QH3B}I:Sp1-SP", "SR:C29-MG{PS:QL1A}I:Sp1-SP", "SR:C29-MG{PS:QL2A}I:Sp1-SP", "SR:C29-MG{PS:QL3A}I:Sp1-SP", "SR:C29-MG{PS:QM1A}I:Sp1-SP", "SR:C29-MG{PS:QM1B}I:Sp1-SP", "SR:C29-MG{PS:QM2A}I:Sp1-SP", "SR:C29-MG{PS:QM2B}I:Sp1-SP", "SR:C29-MG{PS:SQKM1A}I:Sp1-SP", "SR:C30-MG{PS:BT1A}I:Sp1-SP", "SR:C30-MG{PS:BT1A}I:Sp2-SP", "SR:C30-MG{PS:CH1A}I:Sp1-SP", "SR:C30-MG{PS:CH1A}I:Sp2-SP", "SR:C30-MG{PS:CH2A}I:Sp1-SP", "SR:C30-MG{PS:CH2A}I:Sp2-SP", "SR:C30-MG{PS:CL1B}I:Sp1-SP", "SR:C30-MG{PS:CL1B}I:Sp2-SP", "SR:C30-MG{PS:CL2B}I:Sp1-SP", "SR:C30-MG{PS:CL2B}I:Sp2-SP", "SR:C30-MG{PS:CM1A}I:Sp1-SP", "SR:C30-MG{PS:CM1A}I:Sp2-SP", "SR:C30-MG{PS:CM1B}I:Sp1-SP", "SR:C30-MG{PS:CM1B}I:Sp2-SP", "SR:C30-MG{PS:QH1A}I:Sp1-SP", "SR:C30-MG{PS:QH2A}I:Sp1-SP", "SR:C30-MG{PS:QH3A}I:Sp1-SP", "SR:C30-MG{PS:QL1B}I:Sp1-SP", "SR:C30-MG{PS:QL2B}I:Sp1-SP", "SR:C30-MG{PS:QL3B}I:Sp1-SP", "SR:C30-MG{PS:QM1A}I:Sp1-SP", "SR:C30-MG{PS:QM1B}I:Sp1-SP", "SR:C30-MG{PS:QM2A}I:Sp1-SP", "SR:C30-MG{PS:QM2B}I:Sp1-SP", "SR:C30-MG{PS:SH1-P2}I:Sp1-SP", "SR:C30-MG{PS:SH3-P2}I:Sp1-SP", "SR:C30-MG{PS:SQKH1A}I:Sp1-SP"] pvs0 =['SR:C01-MG{PS:SM1A-P2}I:Sp1-SP', 'SR:C02-MG{PS:SM1B-P2}I:Sp1-SP', 'SR:C02-MG{PS:SM2B-P2}I:Sp1-SP', 'SR:C07-MG{PS:SM1A-P3}I:Sp1-SP', 'SR:C08-MG{PS:SM1B-P3}I:Sp1-SP', 'SR:C08-MG{PS:SM2B-P3}I:Sp1-SP', 'SR:C13-MG{PS:SM1A-P4}I:Sp1-SP', 'SR:C14-MG{PS:SM1B-P4}I:Sp1-SP', 'SR:C14-MG{PS:SM2B-P4}I:Sp1-SP', 'SR:C19-MG{PS:SM1A-P5}I:Sp1-SP', 'SR:C20-MG{PS:SM1B-P5}I:Sp1-SP', 'SR:C20-MG{PS:SM2B-P5}I:Sp1-SP', 'SR:C25-MG{PS:SM1A-P1}I:Sp1-SP', 'SR:C26-MG{PS:SM1B-P1}I:Sp1-SP', 'SR:C26-MG{PS:SM2B-P1}I:Sp1-SP'] with self.assertRaises(KeyError) as context: updateconfig(self.conn, self.collection, name, pvlist={"name": pvs0}) self.assertEqual(context.exception.message, 'Cannot find key ("names") for pv names.') self.assertTrue(updateconfig(self.conn, self.collection, name, pvlist={"names": pvs})) res3 = retrieveconfig(self.conn, self.collection, name, withpvs=True) self.assertEqual(res3[0]["status"], "active") self.assertNotEqual(res1[0]["updated_on"], res2[0]["updated_on"]) self.assertEqual(res3[0]["created_on"], res0[0]["created_on"]) self.assertEqual(res3[0]["pvlist"]["names"], pvs) with self.assertRaises(RuntimeError) as context: updateconfig(self.conn, self.collection, name, pvlist={"names": pvs0}) self.assertEqual(context.exception.message, "PV collection list exists already, and should not be changed.")