public void FixedUpdate()
        {
            // do nothing in the editor
            if (Lib.IsEditor())
            {
                return;
            }

            // do nothing if vessel is invalid
            if (!Cache.VesselInfo(vessel).is_valid)
            {
                return;
            }

            // get ec handler
            Resource_Info ec = ResourceCache.Info(vessel, "ElectricCharge");

            // if experiment is active
            if (recording)
            {
                // detect conditions
                // - comparing against amount in previous step
                bool   has_ec       = ec.amount > double.Epsilon;
                bool   has_operator = operator_cs.Check(vessel);
                string sit          = Science.Situation(vessel, situations);

                // deduce issues
                issue = string.Empty;
                if (sit.Length == 0)
                {
                    issue = "invalid situation";
                }
                else if (!has_operator)
                {
                    issue = "no operator";
                }
                else if (!has_ec)
                {
                    issue = "missing <b>EC</b>";
                }

                // if there are no issues
                if (issue.Length == 0)
                {
                    // generate subject id
                    string subject_id = Science.Generate_Subject(experiment, vessel.mainBody, sit, Science.Biome(vessel, sit), Science.Multiplier(vessel, sit));

                    // record in drive
                    if (transmissible)
                    {
                        DB.Vessel(vessel).drive.Record_File(subject_id, data_rate * Kerbalism.elapsed_s);
                    }
                    else
                    {
                        DB.Vessel(vessel).drive.Record_Sample(subject_id, data_rate * Kerbalism.elapsed_s);
                    }

                    // consume ec
                    ec.Consume(ec_rate * Kerbalism.elapsed_s);
                }
            }
        }
        public static void BackgroundUpdate(Vessel v, ProtoPartModuleSnapshot m, Experiment exp, Resource_Info ec, double elapsed_s)
        {
            // if experiment is active
            if (Lib.Proto.GetBool(m, "recording"))
            {
                // detect conditions
                // - comparing against amount in previous step
                bool   has_ec       = ec.amount > double.Epsilon;
                bool   has_operator = new CrewSpecs(exp.crew).Check(v);
                string sit          = Science.Situation(v, exp.situations);

                // deduce issues
                string issue = string.Empty;
                if (sit.Length == 0)
                {
                    issue = "invalid situation";
                }
                else if (!has_operator)
                {
                    issue = "no operator";
                }
                else if (!has_ec)
                {
                    issue = "missing <b>EC</b>";
                }
                Lib.Proto.Set(m, "issue", issue);

                // if there are no issues
                if (issue.Length == 0)
                {
                    // generate subject id
                    string subject_id = Science.Generate_Subject(exp.experiment, v.mainBody, sit, Science.Biome(v, sit), Science.Multiplier(v, sit));

                    // record in drive
                    if (exp.transmissible)
                    {
                        DB.Vessel(v).drive.Record_File(subject_id, exp.data_rate * elapsed_s);
                    }
                    else
                    {
                        DB.Vessel(v).drive.Record_Sample(subject_id, exp.data_rate * elapsed_s);
                    }

                    // consume ec
                    ec.Consume(exp.ec_rate * elapsed_s);
                }
            }
        }