Ejemplo n.º 1
0
    // Start is called before the first frame update
    void Start()
    {
        string data           = "Bell_Dioramas_Touchscreen_FieldGuides_FINAL_CRiver-BigWoods_only.csv";
        string BBSData        = "A2286.csv";
        string RouteData      = "I2286.csv";
        string classification = "classifications.txt";

        Diorama diorama = gameObject.AddComponent <Diorama>();

        Parse.ParseCSV(
            ref diorama,
            Application.streamingAssetsPath + "/" + data,
            Application.streamingAssetsPath + "/" + classification);

        Parse.ParseBBSData(
            ref diorama,
            Application.streamingAssetsPath + "/" + BBSData);

        Parse.ParseRouteData(
            ref diorama,
            Application.streamingAssetsPath + "/" + RouteData);

        //// Visualize all of our population data
        //Visualization visualization = gameObject.AddComponent<Visualization>();


        /*
         * Save our created textures for real-time use
         */
        //for (int i = 0; i < diorama.organisms.Count; i++) {

        //    // Make sure we are only working with birds
        //    if (diorama.organisms[i].classification != Classification.bird) {
        //        continue;
        //    }

        //    // Calculate maxCount at any route
        //    List<float> extrapCounts = new List<float>();
        //    for (int j = 0; j < diorama.popByRoute.Count; j++) { // Route populations
        //        for (int k = 0; k < diorama.popByRoute[j].organisms[i].data.Count; k++) { // years
        //            int count = diorama.popByRoute[j].organisms[i].data[k].count;
        //            int numRoutes = diorama.popByRoute[j].organisms[i].data[k].numRoutes;

        //            extrapCounts.Add(count / (float)numRoutes);
        //        }
        //    }

        //    // Get a ceiling to the nearest 50
        //    int maxCount = Mathf.CeilToInt(Mathf.Max(extrapCounts.ToArray()) / 5.0f) * 5;

        //    // Get a useable save name
        //    string name = diorama.organisms[i].GetName().Trim();
        //    name = name.Replace(" ", "_");
        //    name = name.Replace(",", "");

        //    // Get directory for animal
        //    string dirPath = Application.dataPath + "/Data/" + name + "_" + maxCount.ToString() + "/";
        //    if (!Directory.Exists(dirPath)) {
        //        Directory.CreateDirectory(dirPath);
        //    }

        //    // Run through all years of data on birds
        //    for (int k = 1967; k <= 2017; k++) {
        //        // i is bird index, k is year
        //        Texture2D tex = visualization.Visualize(diorama, MNTexture2D, Colormap, i, k, maxCount);

        //        File.WriteAllBytes(dirPath + k.ToString() + ".png", tex.EncodeToPNG());
        //    }
        //}

        //// Set our sprite now
        //Rect r = new Rect(0, 0, tex.width, tex.height);
        //MNGameObject.GetComponent<SpriteRenderer>().sprite = Sprite.Create(tex, r, new Vector2(0.5f, 0.5f));
    }
Ejemplo n.º 2
0
    /* Runs through our data from BBS and determines counts of birds over
     * years and routes
     */
    public static void ParseBBSData(ref Diorama d, string filepath)
    {
        string[] fileData = System.IO.File.ReadAllLines(filepath);

        List <routeData> routes = new List <routeData>();
        int index;

        // Deep copy of organisms
        List <Organism> copyOfOrganisms = new List <Organism>();

        for (int i = 0; i < d.organisms.Count; i++)
        {
            copyOfOrganisms.Add(d.organisms[i].Clone());
        }

        // First line is text, so start on second
        for (int i = 1; i < fileData.Length; i++)
        {
            string s = fileData[i];

            string[] lineData = s.Trim().Split(',');

            // If we have no info on this route, add it to our list
            string routeId = lineData[2];

            // Get a Deep Copy of our static info
            List <Organism> currClone = new List <Organism>();
            for (int j = 0; j < copyOfOrganisms.Count; j++)
            {
                currClone.Add(copyOfOrganisms[j].Clone());
            }
            routeData r = new routeData {
                routeID   = routeId,
                organisms = currClone
            };

            // Get our current species info
            int      aou = int.Parse(lineData[4]);
            yearData p   = new yearData {
                year      = int.Parse(lineData[3]),
                numRoutes = 1,
                count     = int.Parse(lineData[5])
            };

            // Find the animal with the matching aou so we can add data to it
            for (int k = 0; k < d.organisms.Count; k++)
            {
                if (d.organisms[k].aou == aou)
                {
                    // We have found the matching animal, now we need to see if it
                    // already has data for the year we are on
                    index = d.organisms[k].data.FindIndex(data => data.year == p.year);
                    if (index == -1)
                    {
                        // It did not have existing data, so we add it
                        d.organisms[k].data.Add(p);
                    }
                    else if (d.organisms[k].classification == Classification.bird)
                    {
                        // The data already existed, so now we increment
                        int totalCounts = p.count + d.organisms[k].data[index].count;
                        int totalRoutes = d.organisms[k].data[index].numRoutes + 1;
                        d.organisms[k].data[index] = new yearData {
                            year      = p.year,
                            numRoutes = totalRoutes,
                            count     = totalCounts
                        };
                    }
                }
            }

            // See if we already have this route number, if not add it
            index = routes.FindIndex(route => string.Compare(route.routeID, routeId) == 0);
            if (index == -1)
            {
                routes.Add(r.Clone());
                index = routes.Count - 1;
            }

            // Get a reference to our routes data
            List <Organism> o             = routes[index].organisms;
            int             organismIndex = o.FindIndex(organism => organism.GetAOU() == aou);
            if (o[organismIndex].classification == Classification.bird)
            {
                // Add data on this bird for our route
                index = o[organismIndex].data.FindIndex(data => data.year == p.year);
                if (index == -1)
                {
                    // It did not have existing data, so we add it
                    o[organismIndex].data.Add(p);
                }
                else
                {
                    // The data already existed, so now we increment
                    int totalCounts = p.count + o[organismIndex].data[index].count;
                    int totalRoutes = o[organismIndex].data[index].numRoutes + 1;
                    o[organismIndex].data[index] = new yearData {
                        year      = p.year,
                        numRoutes = totalRoutes,
                        count     = totalCounts
                    };
                }
            }
        }

        // Now that all data is stored in birds, sort them so they are sequential
        for (int i = 0; i < d.organisms.Count; i++)
        {
            d.organisms[i].data.Sort((d1, d2) => d1.year.CompareTo(d2.year));
        }

        // Sort our birds by year, per route
        foreach (routeData p in routes)
        {
            for (int i = 0; i < p.organisms.Count; i++)
            {
                p.organisms[i].data.Sort((d1, d2) => d1.year.CompareTo(d2.year));
            }
        }
        d.popByRoute = routes;
    }
    public Texture2D Visualize(Diorama d, Texture2D MNTexture2D, Texture2D colormap, int birdIndex, int year, int maxCount)
    {
        // Initialization
        popByYear  = new List <extrapPopDataByYear>();
        popByRoute = new List <extrapPopDataByRoute>();

        List <routeData> rData = d.popByRoute;
        Texture2D        tex   = new Texture2D(MNTexture2D.width, MNTexture2D.height);

        Graphics.CopyTexture(MNTexture2D, tex);

        // Get our per-year population data
        foreach (Organism o in d.organisms)
        {
            List <int>   years             = new List <int>();
            List <float> extrapolatedCount = new List <float>();

            for (int i = 0; i < o.GetPopulationData().Count; i++)
            {
                years.Add(o.data[i].year);
                extrapolatedCount.Add(o.data[i].count / (float)o.data[i].numRoutes);
            }

            if (years.Count > 0)
            {
                extrapPopDataByYear b = new extrapPopDataByYear {
                    name              = o.GetName(),
                    years             = years,
                    extrapolatedCount = extrapolatedCount
                };
                popByYear.Add(b);
            }
        }

        // Get extrapolated population by routes
        for (int i = 0; i < d.popByRoute.Count; i++)
        {
            string rId = d.popByRoute[i].routeID;
            List <extrapPopDataByYear> routePop = new List <extrapPopDataByYear>();

            foreach (Organism o in d.popByRoute[i].organisms)
            {
                List <int>   years             = new List <int>();
                List <float> extrapolatedCount = new List <float>();

                for (int k = 0; k < o.GetPopulationData().Count; k++)
                {
                    years.Add(o.data[k].year);
                    extrapolatedCount.Add(o.data[k].count / (float)o.data[k].numRoutes);
                }

                extrapPopDataByYear b = new extrapPopDataByYear {
                    name              = o.GetName(),
                    years             = years,
                    extrapolatedCount = extrapolatedCount
                };
                routePop.Add(b);
            }

            extrapPopDataByRoute r = new extrapPopDataByRoute {
                routeId   = rId,
                popByYear = routePop
            };

            popByRoute.Add(r);
        }

        // Get extrapolated pixel locations of each route
        for (int i = 0; i < rData.Count; i++)
        {
            int x = ChangeScale_FtoI(0, tex.width - 1, minLong, maxLong, rData[i].longitude);
            int y = ChangeScale_FtoI(0, tex.height - 1, minLat, maxLat, rData[i].latitude);

            rData[i] = new routeData {
                routeID   = rData[i].routeID,
                organisms = rData[i].organisms,
                latitude  = rData[i].latitude,
                longitude = rData[i].longitude,
                pixelX    = x,
                pixelY    = y
            };
        }

        // At this point, we now have stored population data by year
        // We have extrapolated our lat/longitude to pixel coordinates

        // Now, we want to change all pixels colors by the data at a specific year at all routes
        // Need a color map

        Color max = Color.white;
        Color min = Color.black;

        Color[] pixels    = tex.GetPixels();
        Color[] newPixels = new Color[pixels.Length];

        float[] values           = new float[popByRoute.Count];
        float[] inverseDistances = new float[popByRoute.Count];
        float[] ratios           = new float[popByRoute.Count];

        List <float> routeCounts = new List <float>();

        // Get our max value found so that we can normalize our colormap
        for (int i = 0; i < popByRoute.Count; i++)
        {
            routeData r = rData[i];

            // Find the route
            int index = popByRoute.FindIndex(route => route.routeId.CompareTo(r.routeID) == 0);

            // Find yearly data in this route
            int yearIndex = popByRoute[index].popByYear[birdIndex].years.IndexOf(year);

            // If it fails, add 0, else add it's pop value
            if (yearIndex == -1)
            {
                routeCounts.Add(0f);
            }
            else
            {
                routeCounts.Add(popByRoute[index].popByYear[birdIndex].extrapolatedCount[yearIndex]);
            }
        }

        /*
         * Starting per-pixel calculations
         */

        for (int i = 0; i < pixels.Length; i++)
        {
            // We don't want to edit transparent sections of the image, black, or white
            if (pixels[i].a == 0 || (pixels[i].r < 0.1f && pixels[i].g < 0.1f && pixels[i].b < 0.1f) ||
                (pixels[i].r > 0.9f && pixels[i].g > 0.9f && pixels[i].b > 0.9f))
            {
                newPixels[i] = pixels[i];
                continue;
            }

            // Initialize pixel value for our Lerp
            float pixelVal = 0;

            // Getting our inverse distance relationship values
            // Further away routes have less impact on pixels color
            int imgWidth  = tex.width;
            int imgHeight = tex.height;
            for (int k = 0; k < popByRoute.Count; k++)
            {
                int   px   = rData[k].pixelX;
                int   py   = rData[k].pixelY;
                int   x    = i % imgWidth;
                int   y    = (i - x) / (imgWidth - 1);
                float dist =
                    (px - x) * (px - x) + (py - y) * (py - y);

                if (dist == 0)
                {
                    dist = 1f;
                }
                inverseDistances[k] = (1.0f / (dist * dist));
            }
            float totalDist = SumArray(inverseDistances);

            // Turn these inverseDistances into ratios to multiply by the pixels
            // Normalize the distances
            float inverseTotalDist = 1.0f / totalDist;
            for (int k = 0; k < popByRoute.Count; k++)
            {
                ratios[k] = inverseDistances[k] * inverseTotalDist;
            }

            // Multiply our pre-computed route population count data by our ratio for this specific pixel
            for (int k = 0; k < popByRoute.Count; k++)
            {
                if (ratios[k] < 0.0001f)
                {
                    values[k] = 0.0f;
                    continue;
                }
                values[k] = (ratios[k] * routeCounts[k]);
            }

            // Need to sum it up and Lerp
            pixelVal     = Mathf.Max(Mathf.Min(SumArray(values) / maxCount, 1), 0);
            newPixels[i] = colormap.GetPixel((colormap.width - 1) - (int)(pixelVal * (colormap.width - 1)), 0);
            //newPixels[i] = Color.Lerp(Color.black, Color.white, Mathf.Clamp(pixelVal, 0.001f, 0.999f));
        }

        // Apply our pixel colors to our textures
        tex.SetPixels(newPixels);
        tex.Apply();

        //    // Draw our route locations on our texture as well for debugging
        //    for (int i = 0; i < rData.Count; i++) {
        //        int x = rData[i].pixelX;
        //        int y = rData[i].pixelY;

        //        MNTexture2D.SetPixel(x, y, Color.black);
        //    }
        //    MNTexture2D.Apply();

        return(tex);
    }