Data Source instantiation

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

Data Source instantiation

bagjohn
I am trying to build a custom dataset. I need to define my datasources.
I need to call functions that return not only single values from agents but also double[] arrays which I want then to process. The dataset editor does not let me do that.

I ve seen  previous posts mentioning the problem and tried to do what is mentioned in one of them : implement AggregateDataSource in my main agent class, where I want to retrieve data from.

But I guess I don't do it right, because after I put my class name to the custom dataset editor line and press ADD i get (The class is not instantiated).

So just to be sure:
Let's say i have a class of agents Mouse.class (e.g. n is the number of mouses in the simulation in the current tick) and want to get a double[m] array from each one of them at every tick (m the dimension of the array retrieved from each agent), perform some operation on the complete double[n][m] array that represents the population of agents at every tick and return a double[m] array for the current tick. Do that for subsequent ticks and watch that array's evolution through time.

So i have :
public class Mouse implements AggregateDataSource

And the interface methods are automatically created. Here is what I did on them :

@Override
        public String getId() {
                // I just made up an id. Do I have to put something specific here?
                return "Mouse";
        }

        @Override
        public Class<?> getDataType() {
                // I just return the datatype i will retrieve from each agent. Correct ?
                return double[].class;
        }

        @Override
        public Class<?> getSourceType() {
                // I just return the class this method is in, which is the same as the one from which the data will be retrieved.
                return Mouse.class;
        }
       
       
        @Override
        public double[] get(Iterable<?> context, int size) {
                // I do not really understand what to do here. My iterable will be the current context which i will scan for objects of type Mouse
                context = ContextUtils.getContext(this);
                List<double[]> Synapse_strengths_list = new ArrayList<double[]>();
                while(context.iterator().hasNext()) {
                        if (context.iterator().next() instanceof Mouse){
                                Object mouse = context.iterator().next();
                                Synapse_strengths_list.add(((Mouse) mouse).getSynapse_strength());
                }
              }
                double[][] Synapse_strengths = new double[ Synapse_strengths_list.size()][];
                Synapse_strengths_list.toArray(Synapse_strengths);
               
                double[] mean_synapse_strengths = new double[Synapse_strengths[0].length];
                for (int j=0; j<Synapse_strengths[0].length; j++) {
                        double sum = 0;
                        for (int i=0; i<Synapse_strengths.length; i++){
                                sum = sum + Synapse_strengths[i][j];
                        }
                        mean_synapse_strengths[j] = sum / Synapse_strengths.length;
                }
                       
               
                return mean_synapse_strengths;
        }

        @Override
        public void reset() {
                // Do I do something here?
               
        }

I guess my problem is this:
Who calls these methods? What arguments should I put?
And is it right to implement the AggregateDataSource on the agent class?

Thank you

Panos
Reply | Threaded
Open this post in threaded view
|

Re: Data Source instantiation

srcnick
You are correct in that you need to implement AggregateDataSource. However, this should be a separate class and not an agent. The idea is that the data collection mechanism will create an instance of that class. It will use the Class returned from your AggregateDataSource’s getSourceType method to create an iterable over agents of that type. That iterable will be passed to your AggregateDataSource’s get(java.lang.Iterable<?> objs, int size) method. In there, you would iterate over agents in the iterable performing whatever aggregate operation you want. In your case that would be gettting the synapse strengh array and working with those as you have in your example.

I’m not sure how well the DataSources will work with returning an array. If you run into trouble, you could try returning a String representation of that array.

Nick


> On Feb 3, 2017, at 7:11 AM, bagjohn <[hidden email]> wrote:
>
> I am trying to build a custom dataset. I need to define my datasources.
> I need to call functions that return not only single values from agents but
> also double[] arrays which I want then to process. The dataset editor does
> not let me do that.
>
> I ve seen  previous  posts
> <http://repast.10935.n7.nabble.com/Data-collection-without-GUI-wizard-td3051.html>  
> mentioning the problem and tried to do what is mentioned in  one of them
> <http://repast.10935.n7.nabble.com/Custom-Data-Source-Help-Repast-Smphony-2-1-td10373.html#a10376>  
> : implement AggregateDataSource in my main agent class, where I want to
> retrieve data from.
>
> But I guess I don't do it right, because after I put my class name to the
> custom dataset editor line and press ADD i get (The class is not
> instantiated).
>
> So just to be sure:
> Let's say i have a class of agents Mouse.class (e.g. n is the number of
> mouses in the simulation in the current tick) and want to get a double[m]
> array from each one of them at every tick (m the dimension of the array
> retrieved from each agent), perform some operation on the complete
> double[n][m] array that represents the population of agents at every tick
> and return a double[m] array for the current tick. Do that for subsequent
> ticks and watch that array's evolution through time.
>
> So i have :
> public class Mouse implements AggregateDataSource
>
> And the interface methods are automatically created. Here is what I did on
> them :
>
> @Override
> public String getId() {
> // I just made up an id. Do I have to put something specific here?
> return "Mouse";
> }
>
> @Override
> public Class<?> getDataType() {
> // I just return the datatype i will retrieve from each agent. Correct ?
> return double[].class;
> }
>
> @Override
> public Class<?> getSourceType() {
> // I just return the class this method is in, which is the same as the one
> from which the data will be retrieved.
> return Mouse.class;
> }
>
>
> @Override
> public double[] get(Iterable<?> context, int size) {
> // I do not really understand what to do here. My iterable will be the
> current context which i will scan for objects of type Mouse
> context = ContextUtils.getContext(this);
> List<double[]> Synapse_strengths_list = new ArrayList<double[]>();
> while(context.iterator().hasNext()) {
> if (context.iterator().next() instanceof Mouse){
> Object mouse = context.iterator().next();
> Synapse_strengths_list.add(((Mouse) mouse).getSynapse_strength());
>        }
>      }
> double[][] Synapse_strengths = new double[
> Synapse_strengths_list.size()][];
> Synapse_strengths_list.toArray(Synapse_strengths);
>
> double[] mean_synapse_strengths = new double[Synapse_strengths[0].length];
> for (int j=0; j<Synapse_strengths[0].length; j++) {
> double sum = 0;
> for (int i=0; i<Synapse_strengths.length; i++){
> sum = sum + Synapse_strengths[i][j];
> }
> mean_synapse_strengths[j] = sum / Synapse_strengths.length;
> }
>
>
> return mean_synapse_strengths;
> }
>
> @Override
> public void reset() {
> // Do I do something here?
>
> }
>
> I guess my problem is this:
> Who calls these methods? What arguments should I put?
> And is it right to implement the AggregateDataSource on the agent class?
>
> Thank you
>
> Panos
>
>
>
> --
> View this message in context: http://repast.10935.n7.nabble.com/Data-Source-instantiation-tp11871.html
> Sent from the repast-interest mailing list archive at Nabble.com.
>
> ------------------------------------------------------------------------------
> Check out the vibrant tech community on one of the world's most
> engaging tech sites, SlashDot.org! http://sdm.link/slashdot
> _______________________________________________
> Repast-interest mailing list
> [hidden email]
> https://lists.sourceforge.net/lists/listinfo/repast-interest


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
_______________________________________________
Repast-interest mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/repast-interest
Reply | Threaded
Open this post in threaded view
|

Re: Data Source instantiation

bagjohn
Yes I managed to do that.
Thank you!
You were right. I have to use Arrays.ToString to export to a file and it is troublesome to import that in R because of the special characters ", [, ] that were incorporated in the file. In order to clear the files before importing in R I used the sed method from within R, in case someone runs into this :

## Pay attention because the following will alter ALL files in the directory
setwd(" ---- Your path to the output files ---")

#Erase letters
system("sed -i 's/[A-Z]//g' *")
system("sed -i 's/[a-z]//g' *")

#Erase the appropriate special characters
system("sed -i 's/[[]//g' *")
system("sed -i 's/[]]//g' *")
system("sed -i 's/[\"]//g' *")

After that, I had a problem with Arrays.ToString exporting doubles in scientific notation, which even after clearing the file were recognized as character strings in R because of the - in between numerics. I decided to use decimal format to avoid this, losing in precision.

DecimalFormat df = new DecimalFormat("##.####");
mean_synapse_strengths[j] = Double.valueOf(df.format(--your_double));

But at least now it works!