// this is the one PartialDeriv that really isn't computed very well w/ the stansard numeric computation method void MultiFlowLevMar::MultiFlowComputePartialDerivOfTimeShift (float *fval,struct bead_params *p, struct reg_params *reg_p, float *neg_sbg_slope) { int fnum; float *vb_out; float *flow_deriv; // parallel fill one bead parameter for block of flows FillBufferParamsBlockFlows (&bkg.my_scratch.cur_buffer_block,p,reg_p,bkg.my_flow.flow_ndx_map,bkg.my_flow.buff_flow); for (fnum=0;fnum<NUMFB;fnum++) { vb_out = fval + fnum*bkg.time_c.npts; // get ptr to start of the function evaluation for the current flow flow_deriv = &neg_sbg_slope[fnum*bkg.time_c.npts]; // get ptr to pre-shifted slope // now this diffeq looks like all the others // because linearity of derivatives gets passed through // flow_deriv in this case is in fact the local derivative with respect to time of the background step // so it can be passed through the equation as though it were a background term BlueSolveBackgroundTrace (vb_out,flow_deriv,bkg.time_c.npts,bkg.time_c.deltaFrame,bkg.my_scratch.cur_buffer_block.tauB[fnum],bkg.my_scratch.cur_buffer_block.etbR[fnum]); // isolate gain and emphasis so we can reuse diffeq code } MultiplyVectorByVector (fval,bkg.my_scratch.custom_emphasis,bkg.my_scratch.bead_flow_t); // gain invariant so can be done to all at once MultiplyVectorByScalar (fval,p->gain,bkg.my_scratch.bead_flow_t); }
// shielding layer to insulate from choice void MathModel::ComputeCumulativeIncorporationHydrogens ( float *ival_offset, int npts, const float *deltaFrameSeconds, const float *nuc_rise_ptr, int SUB_STEPS, int my_start, float C, float A, float SP, float kr, float kmax, float d, float molecules_to_micromolar_conversion, PoissonCDFApproxMemo *math_poiss, int incorporationModelType ) // default value for external calls { bool purely_local = false; if (math_poiss==NULL) { math_poiss = new PoissonCDFApproxMemo; math_poiss->Allocate (MAX_POISSON_TABLE_COL,MAX_POISSON_TABLE_ROW,POISSON_TABLE_STEP); math_poiss->GenerateValues(); purely_local = true; } // handle sign here by "function composition" float tA = A; if (A<0.0f) tA = -A; switch( incorporationModelType ){ case 1: MathModel::ReducedComputeCumulativeIncorporationHydrogens (ival_offset,npts,deltaFrameSeconds,nuc_rise_ptr,SUB_STEPS,my_start,C,tA,SP,kr,kmax,d,molecules_to_micromolar_conversion, math_poiss); break; case 2: MathModel::Reduced2ComputeCumulativeIncorporationHydrogens (ival_offset,npts,deltaFrameSeconds,nuc_rise_ptr,SUB_STEPS,my_start,C,tA,SP,kr,kmax,d,molecules_to_micromolar_conversion, math_poiss); break; case 3: MathModel::Reduced3ComputeCumulativeIncorporationHydrogens (ival_offset,npts,deltaFrameSeconds,nuc_rise_ptr,SUB_STEPS,my_start,C,tA,SP,kr,kmax,d,molecules_to_micromolar_conversion, math_poiss); break; case 0: default: MathModel::SimplifyComputeCumulativeIncorporationHydrogens (ival_offset,npts,deltaFrameSeconds,nuc_rise_ptr,SUB_STEPS,my_start,C,tA,SP,kr,kmax,d, molecules_to_micromolar_conversion, math_poiss); break; } if (purely_local) { delete math_poiss; math_poiss=NULL; } // flip sign: we never have negative incorporations, but we can have cross-talk over-subtracted which we pretend has the same shape if (A<0.0f) MultiplyVectorByScalar (ival_offset,-1.0f,npts); }
void MathModel::ParallelSimpleComputeCumulativeIncorporationHydrogens ( float **ival_offset, int npts, const float *deltaFrameSeconds, const float *const *nuc_rise_ptr, int SUB_STEPS, int *my_start, float *A, float *SP, float *kr, float *kmax, float *d, float *molecules_to_micromolar_conversion, PoissonCDFApproxMemo *math_poiss, int incorporationModelType) { // handle sign here by function composition float tA[FLOW_STEP]; for (int q=0; q<FLOW_STEP; q++) if (A[q]<0.0f) tA[q] = -A[q]; else tA[q] = A[q]; switch( incorporationModelType ){ case 1: for (int q=0; q<FLOW_STEP; q++){ ReducedComputeCumulativeIncorporationHydrogens (ival_offset[q],npts,deltaFrameSeconds,nuc_rise_ptr[q],SUB_STEPS, my_start[q],0,tA[q],SP[q],kr[q],kmax[q],d[q],molecules_to_micromolar_conversion[q], math_poiss); } break; case 2: for (int q=0; q<FLOW_STEP; q++){ Reduced2ComputeCumulativeIncorporationHydrogens (ival_offset[q],npts,deltaFrameSeconds,nuc_rise_ptr[q],SUB_STEPS, my_start[q],0,tA[q],SP[q],kr[q],kmax[q],d[q],molecules_to_micromolar_conversion[q], math_poiss); } break; case 3: for (int q=0; q<FLOW_STEP; q++){ Reduced3ComputeCumulativeIncorporationHydrogens (ival_offset[q],npts,deltaFrameSeconds,nuc_rise_ptr[q],SUB_STEPS, my_start[q],0,tA[q],SP[q],kr[q],kmax[q],d[q],molecules_to_micromolar_conversion[q], math_poiss); } break; case 0: default: UnsignedParallelSimpleComputeCumulativeIncorporationHydrogens (ival_offset,npts,deltaFrameSeconds,nuc_rise_ptr,SUB_STEPS,my_start,tA,SP,kr,kmax,d,molecules_to_micromolar_conversion,math_poiss); break; } // flip sign - we never really have negative incorporation, but we can "over-subtract" cross-talk for (int q=0; q<FLOW_STEP; q++) if (A[q]<0.0f) MultiplyVectorByScalar (ival_offset[q],-1.0f,npts); }
void ParallelSimpleComputeCumulativeIncorporationHydrogens (float **ival_offset, int npts, float *deltaFrameSeconds, float **nuc_rise_ptr, int SUB_STEPS, int *my_start, float *A, float *SP, float *kr, float *kmax, float *d, float *molecules_to_micromolar_conversion, PoissonCDFApproxMemo *math_poiss) { // handle sign here by function composition float tA[FLOW_STEP]; for (int q=0; q<FLOW_STEP; q++) if (A[q]<0.0f) tA[q] = -A[q]; else tA[q] = A[q]; UnsignedParallelSimpleComputeCumulativeIncorporationHydrogens (ival_offset,npts,deltaFrameSeconds,nuc_rise_ptr,SUB_STEPS,my_start,tA,SP,kr,kmax,d,molecules_to_micromolar_conversion,math_poiss); // flip sign - we never really have negative incorporation, but we can "over-subtract" cross-talk for (int q=0; q<FLOW_STEP; q++) if (A[q]<0.0f) MultiplyVectorByScalar (ival_offset[q],-1.0f,npts); }
// shielding layer to insulate from choice void ComputeCumulativeIncorporationHydrogens (float *ival_offset, int npts, float *deltaFrameSeconds, float *nuc_rise_ptr, int SUB_STEPS, int my_start, float C, float A, float SP, float kr, float kmax, float d, float molecules_to_micromolar_conversion, PoissonCDFApproxMemo *math_poiss, bool do_simple) // default value for external calls { bool purely_local = false; if (math_poiss==NULL) { math_poiss = new PoissonCDFApproxMemo; math_poiss->Allocate (MAX_HPLEN+1,512,0.05f); math_poiss->GenerateValues(); purely_local = true; } // handle sign here by "function composition" float tA = A; if (A<0.0f) tA = -A; if (do_simple) { SimplifyComputeCumulativeIncorporationHydrogens (ival_offset,npts,deltaFrameSeconds,nuc_rise_ptr,SUB_STEPS,my_start,C,tA,SP,kr,kmax,d, molecules_to_micromolar_conversion, math_poiss); //SuperSimplifyComputeCumulativeIncorporationHydrogens(ival_offset,npts,deltaFrameSeconds,nuc_rise_ptr,SUB_STEPS,my_start,C,A,SP,kr,kmax,d,math_poiss); } else ComplexComputeCumulativeIncorporationHydrogens (ival_offset,npts,deltaFrameSeconds,nuc_rise_ptr,SUB_STEPS,my_start,C,tA,SP,kr,kmax,d,molecules_to_micromolar_conversion, math_poiss); if (purely_local) { delete math_poiss; math_poiss=NULL; } // flip sign: we never have negative incorporations, but we can have cross-talk over-subtracted which we pretend has the same shape if (A<0.0f) MultiplyVectorByScalar (ival_offset,-1.0f,npts); }
// exploit vectors to get a quick & dirty estimate of amplitude // project onto model trace to get a multiplicative step bringing us closer to alignment with the trace. void SearchAmplitude::ProjectionSearchOneBead ( BeadParams *p, int flow_block_size, int flow_block_start ) const { reg_params *reg_p = &pointer_regions->rp; // technically, need to setup bead correctly here for (int fnum=0; fnum<flow_block_size; fnum++){ p->Ampl[fnum] = 1.0f; // set for projection initiation //p->kmult[fnum] = 1.0f; //? should be set because it might be set differently in some routine before this } // set up bead parameters across flows for this bead // they >might< depend on initial kmult, amplitude MathModel::FillBufferParamsBlockFlows ( my_cur_buffer_block,p,reg_p,my_flow->flow_ndx_map, flow_block_start, flow_block_size ); MathModel::FillIncorporationParamsBlockFlows ( my_cur_bead_block, p,reg_p,my_flow->flow_ndx_map, flow_block_start, flow_block_size ); // this is a more generic "subtract background" routine that we need to think about // reusing for 'oneflowfit' amplitude fitting // need to add cross-talk (0) here so that everything is compatible. // hold all flows of signal at once MathModel::MultiCorrectBeadBkg ( my_scratch->observed,p, *my_scratch,*my_cur_buffer_block, *my_flow,*time_c, *pointer_regions,my_scratch->shifted_bkg, use_vectorization, flow_block_size ); const float *em_vector = emphasis_data->EmphasisVectorByHomopolymer[0]; // incorrect @TODO // @TODO make parallel float block_model_trace[my_scratch->bead_flow_t], block_incorporation_rise[my_scratch->bead_flow_t]; // "In parallel, across flows" const float* nuc_rise_ptr[flow_block_size]; float* model_trace[flow_block_size]; float* incorporation_rise[flow_block_size]; int my_start[flow_block_size]; // setup parallel pointers into the structure for ( int fnum=0; fnum<flow_block_size; fnum++ ) { nuc_rise_ptr[fnum] = pointer_regions->cache_step.NucCoarseStep ( fnum ); model_trace[fnum] = &block_model_trace[fnum*time_c->npts() ]; //tmp_model_trace[fnum] = &tmp_block_model_trace[fnum*time_c->npts() ]; incorporation_rise[fnum] = &block_incorporation_rise[fnum*time_c->npts() ]; // set up each flow information my_start[fnum] = pointer_regions->cache_step.i_start_coarse_step[fnum]; } // now loop calculating model and projecting, multiflow // at this point, we have amplitude = 1.0, krate= default in each flow for ( int projection_loop=0; projection_loop<num_iterations; projection_loop++ ) { // calculate incorporation given parameters for ( int fnum=0; fnum<flow_block_size; fnum++ ) { // can use the parallel trick // compute model based inccorporation trace // also done again and again //p->my_state.hits_by_flow[fnum]++; // temporary MathModel::ComputeCumulativeIncorporationHydrogens ( incorporation_rise[fnum], time_c->npts(), &time_c->deltaFrameSeconds[0], nuc_rise_ptr[fnum], ISIG_SUB_STEPS_MULTI_FLOW, my_start[fnum], my_cur_bead_block->C[fnum], p->Ampl[fnum], my_cur_bead_block->SP[fnum], my_cur_bead_block->kr[fnum], my_cur_bead_block->kmax[fnum], my_cur_bead_block->d[fnum], my_cur_bead_block->molecules_to_micromolar_conversion[fnum], math_poiss, reg_p->hydrogenModelType ); MultiplyVectorByScalar ( incorporation_rise[fnum], my_cur_bead_block->sens[fnum],time_c->npts() ); // transform hydrogens to signal // variables used for solving background signal shape } // can be parallel if ( use_vectorization ) { MathModel::RedSolveHydrogenFlowInWell_Vec ( model_trace,incorporation_rise,time_c->npts(),&time_c->deltaFrame[0],my_cur_buffer_block->tauB, flow_block_size ); // we lose hydrogen ions fast! } else { for ( int fnum=0; fnum<flow_block_size; fnum++ ) { // we do this bit again and again MathModel::RedSolveHydrogenFlowInWell ( model_trace[fnum],incorporation_rise[fnum], time_c->npts(),my_start[fnum],&time_c->deltaFrame[0],my_cur_buffer_block->tauB[fnum] ); } } MultiplyVectorByScalar ( block_model_trace,p->gain,my_scratch->bead_flow_t ); // magic trick: project onto model incorporation trace to find amplitude // because we're "almost" linear this trick works ProjectAmplitude ( p, my_scratch->observed, model_trace, em_vector,time_c->npts(), negative_amplitude_limit, positive_amplitude_limit, flow_block_size ); } }