port from old DO and generalize