def test_abstract(self): with pytest.raises(NotImplementedError): MoleculeDesign(None, None) with pytest.raises(NotImplementedError): SingleStrandedDesign(None) with pytest.raises(NotImplementedError): DoubleStrandedDesign(None)
def run(self): self.add_info('Running molecule design registrar.') self.__check_new_molecule_designs() cs_agg = get_root_aggregate(IChemicalStructure) md_agg = get_root_aggregate(IMoleculeDesign) cs_keys = set() new_css = set() new_mds = set() # Build keys for all new chemical structures. for mdris in self.__new_mdris: # By definition, all mdris for a given hash have the same # structures, so we just take the first. for cs in mdris[0].chemical_structures: cs_keys.add((cs.structure_type_id, cs.representation)) # FIXME: Build a single filtering spec here (see FIXME above). cs_map = {} for cs_key in cs_keys: sti, rpr = cs_key spec = eq(structure_type_id=sti, representation=rpr) cs_agg.filter = spec try: cs = cs_agg.iterator().next() except StopIteration: continue else: cs_map[cs_key] = cs self.add_debug('Creating %d new molecule designs.' % len(self.__new_mdris)) for mdris in self.__new_mdris: md_structs = [] # By definition, all mdris for a given hash have the same # structures, so we just take the first. for struct in mdris[0].chemical_structures: key = (struct.structure_type_id, struct.representation) if not key in cs_map: # New chemical structure - add and use for the design. cs_agg.add(struct) new_css.add(struct) md_structs.append(struct) cs_map[key] = struct else: # Use existing structure for the design. md_structs.append(cs_map[key]) # Create the new design. md = MoleculeDesign.create_from_data( dict(molecule_type=mdris[0].molecule_type, chemical_structures=md_structs)) md_agg.add(md) new_mds.add(md) # Update registration items. for mdri in mdris: mdri.molecule_design = md self.return_value = dict(molecule_designs=new_mds, chemical_structures=new_css)
def __check_new_molecule_designs(self): self.add_debug('Checking for new molecule designs.') md_agg = get_root_aggregate(IMoleculeDesign) # Build a map design hash -> registration item for all molecule design # registration items. mdri_map = {} for mdri in self.registration_items: struc_hash = \ MoleculeDesign.make_structure_hash(mdri.chemical_structures) mdri_map.setdefault(struc_hash, []).append(mdri) # Build "contained" specification, filter all existing designs and # build difference set of new designs. md_agg.filter = cntd(structure_hash=mdri_map.keys()) existing_md_map = dict([(md.structure_hash, md) for md in md_agg.iterator()]) # Update registration items with existing molecule designs and # remove from hash map. for struc_hash, md in existing_md_map.iteritems(): mdris = mdri_map.pop(struc_hash) for mdri in mdris: mdri.molecule_design = md self.__new_mdris = list(mdri_map.values())
def __check_new_supplier_molecule_designs(self): self.add_debug('Checking for new supplier molecule designs.') smd_agg = get_root_aggregate(ISupplierMoleculeDesign) # FIXME: We should really build a single filtering spec here like so: # spec = reduce(or_, # [eq(supplier=sri.supplier, product_id=sri.product_id) # for in in self.sample_registration_items]) # However, this leads to "maximum recursion depth exceeded" # problems with the current everest. exst_smd_map = {} for sri in self.registration_items: smd_spec = eq(supplier=sri.supplier, product_id=sri.product_id, is_current=True) smd_agg.filter = smd_spec try: smd = next(smd_agg.iterator()) except StopIteration: continue else: exst_smd_map[(smd.supplier, smd.product_id)] = smd new_smd_sri_map = {} for sri in self.registration_items: mdpri = sri.molecule_design_pool_registration_item # Set the molecule type. mdpri.molecule_type = sri.molecule_type key = (sri.supplier, sri.product_id) if key in exst_smd_map: # Update sample registration item. smd = exst_smd_map[key] sri.supplier_molecule_design = smd if not smd.molecule_design_pool is None: # Compare found design information against existing design # information. mdris = mdpri.molecule_design_registration_items found_md_hashes = \ sorted([MoleculeDesign.make_structure_hash( mdri.chemical_structures) for mdri in mdris]) exist_mds = smd.molecule_design_pool.molecule_designs exist_md_hashes = sorted([md.structure_hash for md in exist_mds]) if found_md_hashes != exist_md_hashes: msg = 'For product ID "%s" and supplier "%s", a ' \ 'supplier molecule design exists which has ' \ 'different design information than the one ' \ 'included in the current registration.' \ % (sri.product_id, sri.supplier.name) self.add_error(msg) continue else: # FIXME: Should this be a warning instead? msg = 'For product ID "%s" and supplier "%s", a ' \ 'supplier molecule design was found which does ' \ 'not have an associated molecule design pool.' \ % (sri.product_id, sri.supplier.name) self.add_error(msg) continue else: # We use a map here so that multiple sample registration items # with the same supplier molecule design information create # only a single new supplier molecule design. new_smd_sri_map.setdefault(key, []).append(sri) # Store new supplier molecule design registration items for later use. self.__new_smd_sri_map = new_smd_sri_map