Переопределение функции в пакете R

Я попытался изменить и переопределить функцию (xcmsRaw) в пакете R xcms, сначала определив функцию

my.xcmsRaw <- function(filename, profstep = 1, profmethod = "bin",
                    profparam = list(mzcorrf=1),    # PATCH - mzcorrf is the m/z correction factor, e.g. 0.99888 for long-chain hydrocarbons
                    includeMSn = FALSE, mslevel=NULL,
                    scanrange=NULL) { ... }

а затем набрав

unlockBinding("xcmsRaw", as.environment("package:xcms"))
assign("xcmsRaw", my.xcmsRaw, as.environment("package:xcms"))
lockBinding("xcmsRaw", as.environment("package:xcms"))

Однако при запуске выдает ошибку

Error in get(as.character(FUN), mode = "function", envir = envir) : 
  object 'profBinM' of mode 'function' was not found

вызвано тем, что он не находит функцию profBinM, которая является функцией кода C, определенной в файле xcms.c пакета xcms.

Любые мысли о том, как я могу решить эту проблему? (Я работаю под Windows 7, используя R версии 3.0.0)


person Tom Wenseleers    schedule 01.05.2013    source источник
comment
Пробовали ли вы assignInNamespace(), как, например, в этом примере ? В вашем случае вы бы использовали что-то вроде assignInNamespace(x="xcmsRaw", value="my.xcmsRaw", ns=asNamespace("xcms")).   -  person Josh O'Brien    schedule 01.05.2013
comment
Спасибо за предложение, только что попробовал, но, к сожалению, все равно выдает ту же ошибку...   -  person Tom Wenseleers    schedule 01.05.2013
comment
Интересно. Чтобы быть точным/ясным, profBinM() - это функция R, обертывающая функцию C.   -  person Josh O'Brien    schedule 01.05.2013
comment
Да, эта функция определена в файле xcms.c (в Windows это, конечно, уже было бы предварительно скомпилировано) как void ProfBinM(double *xvals, double *yvals, int *numin, int *mindex, int *nummi, double *xstart, double *xend, int *numout, double *out) { ... }   -  person Tom Wenseleers    schedule 01.05.2013
comment
Вы пытались сделать trace(xcmsRaw, edit=TRUE) и внести изменения таким образом?   -  person Josh O'Brien    schedule 01.05.2013
comment
Да, только что попробовал, и это, кажется, работает - хотя я не могу изменить аргументы или значения по умолчанию функции с помощью этого   -  person Tom Wenseleers    schedule 01.05.2013
comment
И знаете ли вы, как я могу внести изменения в код, не вводя его вручную в редакторе? В моем случае я хотел бы автоматически вставить строку if ((profparam$mzcorrf!=1)&length(unique(rawdata$mz - trunc(rawdata$mz)))!=1) {rawdata$mz=rawdata$mz *profparam$mzcorrf} else if (profparam$mzcorrf!=1) {print(Точные массы уже были округлены до номинальных масс);profparam$mzcorrf=1} после строки 7 исходной функции?   -  person Tom Wenseleers    schedule 01.05.2013
comment
Большое спасибо за это! Получил это работает сейчас! Тем не менее, было бы неплохо заставить его работать через assignInNamespace(), так как это позволило бы вносить более обширные изменения/переопределения...   -  person Tom Wenseleers    schedule 01.05.2013


Ответы (1)


Спасибо, Джош - в моем случае у меня все заработало через

modifline='if ((profparam$mzcorrf!=1)&length(unique(rawdata$mz - trunc(rawdata$mz)))!=1) {rawdata$mz=rawdata$mz*profparam$mzcorrf} else if (profparam$mzcorrf!=1) {print("Exact masses were already rounded to nominal masses");profparam$mzcorrf=1}'
insertatline=6
trace(xcmsRaw, tracer=modifline,at=c(insertatline))

где я нашел правильную строку для вставки моего измененного кода, используя

as.list(body(xcmsRaw))

Чтобы подавить вывод трассировки, я определил вторую функцию

xcmsRaw2=function(...) {sink("NUL");obj=xcmsRaw(...);sink();return(obj) }

который можно вызвать и который не предоставляет никаких ненужных выходных данных трассировки.

Тем не менее было бы неплохо заставить его работать и через assignInNamespace(), так как это позволило бы более обширно редактировать/переопределять, а также изменять аргументы функции (что было бы общей причиной для переопределения функций, т.е. лишний аргумент)...

person Tom Wenseleers    schedule 01.05.2013
comment
Здорово! Я согласен, это похоже на взлом, но это проблема. намного лучше, чем ничего, пока вы не найдете более гибкое/элегантное решение. - person Josh O'Brien; 01.05.2013
comment
Ах да, и есть ли способ подавить вывод трассировки? Теперь каждый раз, когда я вызываю xcmsRaw, он будет печатать Tracing xcmsRaw(files[samplenr], profstep = profst, profmethod = bin, .... шаг 6, но я хотел бы подавить этот вывод. Есть ли способ сделать это? - person Tom Wenseleers; 02.05.2013
comment
Моей единственной идеей было бы обернуть ваш вызов xcmsRaw() в suppressMessages(). Если это сработает, вы можете написать очень тонкую функцию-оболочку — возможно, назовите ее xcmsRaw2 — которая передает все аргументы в suppressMessages(xcmsRaw(...)). Но помните, что это будет работать только для прямых вызовов xcmsRaw, а не вызовов из других функций в пакете. В качестве альтернативы вы можете просто изменить исходный код пакета и перекомпилировать версию, содержащую ваш новый и улучшенный xcmsRaw ;) - person Josh O'Brien; 02.05.2013
comment
Как ни странно, если я определяю xcmsRaw2=function(...) {suppressMessages(xcmsRaw(...))}, я все еще получаю Tracing xcmsRaw(...) шаг 6 в качестве вывода, так что, похоже, это не работает... Так что да, придется перекомпилировать, но это будет какой-то беспорядок, так как я хотел бы упаковать его вместе с моим пакетом, а затем мне придется выяснить, какой код я буду и не должен копировать. . - person Tom Wenseleers; 02.05.2013
comment
Ха, но xcmsRaw2=function(...) {sink(NUL);obj=xcmsRaw(...);sink();return(obj) } сделал свое дело... Спасибо за это! - person Tom Wenseleers; 02.05.2013
comment
О Конечно. Чтобы suppressMessages() работало, вам нужно было бы использовать message(), а не print() для вывода уведомления о точных массах .... Если подумать, это на самом деле может быть более чистым решением. Ваше здоровье! - person Josh O'Brien; 02.05.2013
comment
Еще одна мысль. Что касается переопределения функции в пространстве имен с другими/дополнительными аргументами, я полагаю, что разработчики R намеренно сделали это трудным или, возможно, невозможным. Я предполагаю, что это приглашение к такому хаосу (для любых других ранее существовавших функций или кода, который полагался на эту функцию), что разработчики R не так мягко подталкивают вас к поиску других решений! - person Josh O'Brien; 02.05.2013
comment
Да, это, конечно, похоже на ужасный хак... Простым вариантом было бы, если бы разработчикам xcms понравилось мое расширение и они внедрили его, но, похоже, нет, хе-хе... :-) - person Tom Wenseleers; 02.05.2013