@@ -338,142 +338,154 @@ pc_prop <- function(cid, properties = NULL, verbose = getOption("verbose"), ...)
338338 if (! ping_service(" pc" )) stop(webchem_message(" service_down" ))
339339
340340 cid_o <- cid
341-
342- if (verbose ) message(" Coercing queries to positive integers. " , appendLF = FALSE )
343-
344341 cid <- suppressWarnings(as.integer(cid ))
345342
343+ invalid <- is.na(cid ) | cid < = 0
344+ cid [invalid ] <- NA_integer_
345+
346346 if (verbose ) {
347- index <- which(is.na(cid ) & ! is.na(cid_o ))
347+ message(" Coercing queries to positive integers. " , appendLF = FALSE )
348+ index <- which(invalid & ! is.na(cid_o ))
348349 if (length(index ) > 0 ) {
349350 for (i in index ) {
350- message(paste0(cid_o [index ], " coerced to NA. " ), appendLF = FALSE )
351- }
352- }
353- }
354-
355- if (any(cid < = 0 , na.rm = TRUE )) {
356- index <- which(cid < = 0 )
357- cid [index ] <- NA
358- if (verbose ) {
359- for (i in index ) {
360- message(paste0(cid_o [index ], " coerced to NA. " ), appendLF = FALSE )
351+ message(paste0(cid_o [i ], " coerced to NA. " ), appendLF = FALSE )
361352 }
362353 }
354+ message(" Done." )
363355 }
364356
365- if (verbose ) message(" Done." )
357+ vcids <- tibble :: tibble(
358+ query = cid_o ,
359+ cid = cid
360+ )
366361
367- if (mean(is.na(cid )) == 1 ) {
362+ if (mean(is.na(vcids $ cid )) == 1 ) {
368363 if (verbose ) webchem_message(" na" )
369364 return (NA )
370365 }
371366
372- napos <- which(is.na(cid ))
373- cid <- cid [! is.na(cid )]
367+ cid <- vcids $ cid [! is.na(vcids $ cid )]
374368 prolog <- " https://pubchem.ncbi.nlm.nih.gov/rest/pug"
375- input <- " /compound/cid"
376- if (is.null(properties ))
377- properties <- c(
378- " MolecularFormula" ,
379- " MolecularWeight" ,
380- " SMILES" ,
381- " ConnectivitySMILES" ,
382- " InChI" ,
383- " InChIKey" ,
384- " IUPACName" ,
385- " Title" ,
386- " XLogP" ,
387- " ExactMass" ,
388- " MonoisotopicMass" ,
389- " TPSA" ,
390- " Complexity" ,
391- " Charge" ,
392- " HBondDonorCount" ,
393- " HBondAcceptorCount" ,
394- " RotatableBondCount" ,
395- " HeavyAtomCount" ,
396- " IsotopeAtomCount" ,
397- " AtomStereoCount" ,
398- " DefinedAtomStereoCount" ,
399- " UndefinedAtomStereoCount" ,
400- " BondStereoCount" ,
401- " DefinedBondStereoCount" ,
402- " UndefinedBondStereoCount" ,
403- " CovalentUnitCount" ,
404- " PatentCount" ,
405- " PatentFamilyCount" ,
406- " AnnotationTypes" ,
407- " AnnotationTypeCount" ,
408- " SourceCategories" ,
409- " LiteratureCount" ,
410- " Volume3D" ,
411- " XStericQuadrupole3D" ,
412- " YStericQuadrupole3D" ,
413- " ZStericQuadrupole3D" ,
414- " FeatureCount3D" ,
415- " FeatureAcceptorCount3D" ,
416- " FeatureDonorCount3D" ,
417- " FeatureAnionCount3D" ,
418- " FeatureCationCount3D" ,
419- " FeatureRingCount3D" ,
420- " FeatureHydrophobeCount3D" ,
421- " ConformerModelRMSD3D" ,
422- " EffectiveRotorCount3D" ,
423- " ConformerCount3D" ,
424- " Fingerprint2D"
425- )
369+ input <- " /compound/cid/"
370+ all_properties <- c(
371+ " MolecularFormula" ,
372+ " MolecularWeight" ,
373+ " SMILES" ,
374+ " ConnectivitySMILES" ,
375+ " InChI" ,
376+ " InChIKey" ,
377+ " IUPACName" ,
378+ " Title" ,
379+ " XLogP" ,
380+ " ExactMass" ,
381+ " MonoisotopicMass" ,
382+ " TPSA" ,
383+ " Complexity" ,
384+ " Charge" ,
385+ " HBondDonorCount" ,
386+ " HBondAcceptorCount" ,
387+ " RotatableBondCount" ,
388+ " HeavyAtomCount" ,
389+ " IsotopeAtomCount" ,
390+ " AtomStereoCount" ,
391+ " DefinedAtomStereoCount" ,
392+ " UndefinedAtomStereoCount" ,
393+ " BondStereoCount" ,
394+ " DefinedBondStereoCount" ,
395+ " UndefinedBondStereoCount" ,
396+ " CovalentUnitCount" ,
397+ " PatentCount" ,
398+ " PatentFamilyCount" ,
399+ " AnnotationTypes" ,
400+ " AnnotationTypeCount" ,
401+ " SourceCategories" ,
402+ " LiteratureCount" ,
403+ " Volume3D" ,
404+ " XStericQuadrupole3D" ,
405+ " YStericQuadrupole3D" ,
406+ " ZStericQuadrupole3D" ,
407+ " FeatureCount3D" ,
408+ " FeatureAcceptorCount3D" ,
409+ " FeatureDonorCount3D" ,
410+ " FeatureAnionCount3D" ,
411+ " FeatureCationCount3D" ,
412+ " FeatureRingCount3D" ,
413+ " FeatureHydrophobeCount3D" ,
414+ " ConformerModelRMSD3D" ,
415+ " EffectiveRotorCount3D" ,
416+ " ConformerCount3D" ,
417+ " Fingerprint2D"
418+ )
419+ if (is.null(properties )) {
420+ properties <- all_properties
421+ } else {
422+ invalid_props <- setdiff(properties , all_properties )
423+ if (length(invalid_props ) > 0 ) {
424+ stop(
425+ " Invalid properties: " ,
426+ paste(invalid_props , collapse = " , " ),
427+ " . Valid properties: " ,
428+ all_properties | > sort() | > paste(collapse = " , " ),
429+ call. = FALSE
430+ )
431+ }
432+ }
426433 properties <- paste(properties , collapse = " ," )
427434 output <- paste0(" /property/" , properties , " /JSON" )
428435
429- qurl <- paste0(prolog , input , output )
430- if (verbose ) webchem_message(" query_all" , appendLF = FALSE )
431- webchem_sleep(type = ' API' )
432- res <- try(httr :: RETRY(" POST" ,
433- qurl ,
434- httr :: user_agent(webchem_url()),
435- body = list (" cid" = paste(cid , collapse = " ," )),
436- terminate_on = 404 ,
437- quiet = TRUE ), silent = TRUE )
438- if (inherits(res , " try-error" )) {
439- if (verbose ) webchem_message(" service_down" )
440- return (NA )
441- }
442- if (verbose ) message(httr :: message_for_status(res ))
443- if (res $ status_code == 200 ) {
444- cont <- jsonlite :: fromJSON(rawToChar(res $ content ))
445- if (names(cont ) == " Fault" ) {
446- if (verbose ) {
447- message(cont $ Fault $ Message , " . " , cont $ Fault $ Details , " . Returning NA." )
448- }
449- return (NA )
436+ foo <- function (x ) {
437+ qurl <- paste0(prolog , input , x , output )
438+ if (verbose ) webchem_message(" query" , x , appendLF = FALSE )
439+ webchem_sleep(type = ' API' )
440+ res <- try(httr :: RETRY(" GET" ,
441+ qurl ,
442+ httr :: user_agent(webchem_url()),
443+ terminate_on = 404 ,
444+ quiet = TRUE ), silent = TRUE )
445+ if (inherits(res , " try-error" )) {
446+ if (verbose ) webchem_message(" service_down" )
447+ return (data.frame ())
450448 }
451- out <- cont $ PropertyTable [[1 ]]
452- # insert NA rows
453- narow <- rep(NA , ncol(out ))
454- for (i in seq_along(napos )) {
455- # capture NAs at beginning
456- firstnna <- min(which(! is.na(cid_o )))
457- if (napos [i ] < firstnna ) {
458- out <- rbind(narow , out )
459- } else {
460- # capture NAs at end
461- if (napos [i ] > nrow(out )) {
462- # print(napos[i])
463- out <- rbind(out , narow )
464- } else {
465- out <- rbind(out [1 : (napos [i ] - 1 ), ], narow , out [napos [i ]: nrow(out ), ])
449+ if (verbose ) message(httr :: message_for_status(res ))
450+ if (res $ status_code == 200 ) {
451+ cont <- jsonlite :: fromJSON(rawToChar(res $ content ))
452+ if (names(cont ) == " Fault" ) {
453+ if (verbose ) {
454+ message(cont $ Fault $ Message , " . " , cont $ Fault $ Details , " . Returning NA." )
466455 }
467- }}
468- rownames(out ) <- NULL
469- out $ CID <- cid_o
470- out <- tibble :: as_tibble(out )
471- class(out ) <- c(" pc_prop" , class(out ))
472- return (out )
473- }
474- else {
475- return (NA )
456+ return (data.frame ())
457+ }
458+ out <- cont $ PropertyTable [[1 ]]
459+ out <- out | > dplyr :: mutate(CID = x ) | > dplyr :: relocate(CID )
460+ return (out )
461+ } else {
462+ return (data.frame ())
463+ }
476464 }
465+ out <- lapply(cid , foo ) | > dplyr :: bind_rows()
466+
467+ if (nrow(out ) == 0 ) return (NA )
468+
469+ na_row <- as.data.frame(as.list(rep(NA , ncol(out ))))
470+ names(na_row ) <- names(out )
471+ out_list <- lapply(seq_len(nrow(vcids )), function (i ) {
472+ if (is.na(vcids $ cid [i ])) {
473+ na_row $ CID <- vcids $ query [i ]
474+ return (na_row )
475+ } else {
476+ hit <- out [which(out $ CID == vcids $ query [i ]),]
477+ if (nrow(hit ) == 0 ) {
478+ na_row $ CID <- vcids $ query [i ]
479+ return (na_row )
480+ } else {
481+ return (hit )
482+ }
483+ }
484+ })
485+ out <- do.call(rbind , out_list )
486+ out <- tibble :: as_tibble(out )
487+ class(out ) <- c(" pc_prop" , class(out ))
488+ return (out )
477489}
478490
479491# ' Search synonyms in pubchem
0 commit comments