/// <summary> /// Execute a timestep, manipulating data accordingly /// </summary> /// <param name="cell">The cell to which this component belongs</param> /// <param name="state">The current environment state</param> /// <param name="time">Simulation time</param> /// <param name="timeStep">Simulation time step</param> public override void DoTimeStep(CellInstance cell, ComponentWorldStateBase compData,StateSnapshot state, double time, double timeStep) { FlagellaWorldState flage = (FlagellaWorldState)compData; //NutrientField attractant = state.SimulationEnvironment.GetNutrientFieldObject(attractantIndex); //NutrientField repellent = state.SimulationEnvironment.GetNutrientFieldObject(repellentIndex); float valueFromCircuit = (float)cell.getLocalSimulationSpeciesAmount(getSpeciesReference(0, ComponentLinkType.Input).species.ID); if (flage.TumbleState) { flage.TumbleCounter += (float)timeStep; //end of tumble if (flage.TumbleCounter > tumbleDuration) { cell.CellInstanceSpatialContext.Reorientate(new Vector3((float)(cell.GetRandomObject().NextDouble() * 2 - 1), (float)(cell.GetRandomObject().NextDouble() * 2 - 1), (float)(cell.GetRandomObject().NextDouble() * 2 - 1))); flage.TumbleState = false; //up to 50% varience in next tumble duration flage.TumbleCounter = 0.0f + tumbleDuration*0.5f*(float)cell.GetRandomObject().NextDouble(); } } else { flage.TumbleUpdateCounter += (float)timeStep; //Randomly decide whether or not to tumble according to some likelihood if (flage.TumbleUpdateCounter > 1.0f / TumbleUpdateFrequency) { float val = flage.TumbleLikelihood - (float)cell.GetRandomObject().NextDouble(); if (flage.TumbleLikelihood - (float)cell.GetRandomObject().NextDouble() > 0) { //tumble flage.TumbleState = true; } flage.TumbleUpdateCounter = 0.0f; } flage.SampleCounter += (float)timeStep; //propel cell forward cell.CellInstanceSpatialContext.Accelerate(new Vector3( cell.CellInstanceSpatialContext.Orientation.x * motiveStength * (float)timeStep, cell.CellInstanceSpatialContext.Orientation.y * motiveStength * (float)timeStep, cell.CellInstanceSpatialContext.Orientation.z * motiveStength * (float)timeStep)); if (flage.SampleCounter > 0.4f) { /* if (!flage.FirstSampleTaken) { //flage.FirstSample = attractant.GetNutrientLevel(cell.CellInstanceSpatialContext.Position); flage.FirstSample = valueFromCircuit; flage.FirstSampleTaken = true; }*/ } if (flage.SampleCounter > 0.8f) { // float SecondSample = attractant.GetNutrientLevel(cell.CellInstanceSpatialContext.Position); /* float SecondSample = valueFromCircuit; if (SecondSample > flage.FirstSample) { //continue going straight flage.TumbleLikelihood = 0.001f; } else { //tumble flage.TumbleLikelihood = 0.995f; }*/ if (valueFromCircuit > 1.0f) { flage.TumbleLikelihood = 0.90f; } else { flage.TumbleLikelihood = 0.1f; } flage.SampleCounter = 0.0f; // flage.FirstSampleTaken = false; } } }