pub fn partitions_file(positions: Vec<(String, String, String)>,
                       partitioned_density: &[Vec<f64>],
                       partitioned_volume: &[f64],
                       total_density: &[f64],
                       total_volume: f64,
                       distance: &[f64],
                       atom_map: Option<&[usize]>)
                       -> Result<String> {
    // calculate the total density for each density supplied
    let total_partitioned_density =
        partitioned_density.iter().fold(vec![
                                            0.0;
                                            partitioned_density[0].len()
                                        ],
                                        |mut sum, d| {
                                            sum.iter_mut()
                                               .zip(d)
                                               .for_each(|(tpd, pd)| {
                                                   *tpd += pd
                                               });
                                            sum
                                        });
    // the volume is the same for all densities
    let total_partitioned_volume = partitioned_volume.iter().sum();
    let vacuum_density = total_partitioned_density.iter()
                                                  .zip(total_density)
                                                  .map(|(a, b)| b - a)
                                                  .collect::<Vec<f64>>();
    let vacuum_volume = total_volume - total_partitioned_volume;
    // which charge file to write, if there's an atom_map -> BCF
    if let Some(atom_map) = atom_map {
        let mut table =
            Table::new(TableType::BaderCharge, partitioned_density[0].len());
        let mut index: Vec<usize> = (0..atom_map.len()).collect();
        index.sort_by(|a, b| atom_map[*a].cmp(&atom_map[*b]));
        let mut atom_num = atom_map[index[0]];
        table.separators.push(atom_num + 1);
        index.into_iter().for_each(|i| {
                             let a = atom_map[i];
                             if a != atom_num {
                                 table.add_separator(a + 1);
                                 atom_num = a
                             }
                             table.add_row(i,
                                           positions[i].clone(),
                                           &partitioned_density[i],
                                           partitioned_volume[i],
                                           distance[i]);
                         });
        Ok(table.get_string(&vacuum_density,
                            vacuum_volume,
                            &total_partitioned_density,
                            total_partitioned_volume))
    // if no atom_map -> ACF
    } else {
        let mut table =
            Table::new(TableType::AtomsCharge, partitioned_density[0].len());
        let mut index = 1;
        positions.into_iter()
                 .zip(partitioned_density)
                 .zip(partitioned_volume)
                 .zip(distance)
                 .for_each(|(((coord, density), volume), distance)| {
                     table.add_row(index, coord, density, *volume, *distance);
                     index += 1;
                 });
        Ok(table.get_string(&vacuum_density,
                            vacuum_volume,
                            &total_partitioned_density,
                            total_partitioned_volume))
    }
}
/// Create the partitioned charge files using an optional atom map to decide the format
Create the partitioned charge files using an optional atom map to decide the format
Create the partitioned charge files using an optional atom map to decide the format
pub fn partitions_file(positions: Vec<(String, String, String)>,
                       partitioned_density: &[Vec<f64>],
                       partitioned_volume: &[f64],
                       total_density: &[f64],
                       total_volume: f64,
                       distance: &[f64],
                       atom_map: Option<&[usize]>)
                       -> Result<String> {
    // calculate the total density for each density supplied
    let total_partitioned_density =
        partitioned_density.iter().fold(vec![
                                            0.0;
                                            partitioned_density[0].len()
                                        ],
                                        |mut sum, d| {
                                            sum.iter_mut()
                                               .zip(d)
                                               .for_each(|(tpd, pd)| {
                                                   *tpd += pd
                                               });
                                            sum
                                        });
    // the volume is the same for all densities
    let total_partitioned_volume = partitioned_volume.iter().sum();
    let vacuum_density = total_partitioned_density.iter()
                                                  .zip(total_density)
                                                  .map(|(a, b)| b - a)
                                                  .collect::<Vec<f64>>();
    let vacuum_volume = total_volume - total_partitioned_volume;
    // which charge file to write, if there's an atom_map -> BCF
    if let Some(atom_map) = atom_map {
        let mut table =
            Table::new(TableType::BaderCharge, partitioned_density[0].len());
        let mut index: Vec<usize> = (0..atom_map.len()).collect();
        index.sort_by(|a, b| atom_map[*a].cmp(&atom_map[*b]));
        let mut atom_num = atom_map[index[0]];
        table.separators.push(atom_num + 1);
        index.into_iter().for_each(|i| {
                             let a = atom_map[i];
                             if a != atom_num {
                                 table.add_separator(a + 1);
                                 atom_num = a
                             }
                             table.add_row(i,
                                           positions[i].clone(),
                                           &partitioned_density[i],
                                           partitioned_volume[i],
                                           distance[i]);
                         });
        Ok(table.get_string(&vacuum_density,
                            vacuum_volume,
                            &total_partitioned_density,
                            total_partitioned_volume))
    // if no atom_map -> ACF
    } else {
        let mut table =
            Table::new(TableType::AtomsCharge, partitioned_density[0].len());
        let mut index = 1;
        positions.into_iter()
                 .zip(partitioned_density)
                 .zip(partitioned_volume)
                 .zip(distance)
                 .for_each(|(((coord, density), volume), distance)| {
                     table.add_row(index, coord, density, *volume, *distance);
                     index += 1;
                 });
        Ok(table.get_string(&vacuum_density,
                            vacuum_volume,
                            &total_partitioned_density,
                            total_partitioned_volume))
    }
}
pub fn partitions_file ( positions : Vec < ( String , String , String ) > , partitioned_density : & [ Vec < f64 > ] , partitioned_volume : & [ f64 ] , total_density : & [ f64 ] , total_volume : f64 , distance : & [ f64 ] , atom_map : Option < & [ usize ] > ) -> Result < String > { // calculate the total density for each density supplied let total_partitioned_density = partitioned_density . iter ( ) . fold ( vec ! [ 0.0 partitioned_density [ 0 ] len ( ) ] , | mut sum , d | { sum . iter_mut ( ) . zip ( d ) . for_each ( | ( tpd , pd ) | { * tpd += pd } ) ; sum } ) ; // the volume is the same for all densities let total_partitioned_volume = partitioned_volume . iter ( ) . sum ( ) ; let vacuum_density = total_partitioned_density . iter ( ) . zip ( total_density ) . map ( | ( a , b ) | b - a ) . collect :: < Vec < f64 > > ( ) ; let vacuum_volume = total_volume - total_partitioned_volume ; // which charge file to write, if there's an atom_map -> BCF if let Some ( atom_map ) = atom_map { let mut table = Table :: new ( TableType :: BaderCharge , partitioned_density [ 0 ] . len ( ) ) ; let mut index : Vec < usize > = ( 0 .. atom_map . len ( ) ) . collect ( ) ; index . sort_by ( | a , b | atom_map [ * a ] . cmp ( & atom_map [ * b ] ) ) ; let mut atom_num = atom_map [ index [ 0 ] ] ; table . separators . push ( atom_num + 1 ) ; index . into_iter ( ) . for_each ( | i | { let a = atom_map [ i ] ; if a != atom_num { table . add_separator ( a + 1 ) ; atom_num = a } table . add_row ( i , positions [ i ] . clone ( ) , & partitioned_density [ i ] , partitioned_volume [ i ] , distance [ i ] ) ; } ) ; Ok ( table . get_string ( & vacuum_density , vacuum_volume , & total_partitioned_density , total_partitioned_volume ) ) // if no atom_map -> ACF } else { let mut table = Table :: new ( TableType :: AtomsCharge , partitioned_density [ 0 ] . len ( ) ) ; let mut index = 1 ; positions . into_iter ( ) . zip ( partitioned_density ) . zip ( partitioned_volume ) . zip ( distance ) . for_each ( | ( ( ( coord , density ) , volume ) , distance ) | { table . add_row ( index , coord , density , * volume , * distance ) ; index += 1 ; } ) ; Ok ( table . get_string ( & vacuum_density , vacuum_volume , & total_partitioned_density , total_partitioned_volume ) ) } }
Create the partitioned charge files using an optional atom map to decide the format
Create the partitioned charge files using an optional atom map to decide the format
positions
Vec<(String, String, String)>
partitioned_density
&[Vec<f64>]
partitioned_volume
&[f64]
total_density
&[f64]
total_volume
f64
distance
&[f64]
atom_map
Option<&[usize]>
positions
Vec<(String, String, String)>
partitioned_density
&[Vec<f64>]
partitioned_volume
&[f64]
total_density
&[f64]
total_volume
f64
distance
&[f64]
atom_map
Option<&[usize]>